From afb17cb62df8fbbe4c50921945e0b462094c3fae Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Wed, 13 Oct 2021 14:55:33 +0200 Subject: [PATCH] Patched Origami Pattern --- .../OrigamiPatterns/Bendy_Straw.py | 369 ++++++++++++++++++ .../OrigamiPatterns/Kresling_full.py | 2 - .../origami_patterns/OrigamiPatterns/Path.py | 114 +++++- .../OrigamiPatterns/Pattern.py | 42 +- .../OrigamiPatterns/SupportRing.py | 86 ++++ .../origami_patterns_bendy_straw.inx | 105 +++++ .../origami_patterns_kresling.inx | 11 +- .../origami_patterns_misc_support_ring.inx | 48 +++ .../origami_patterns_pleat_circular.inx | 11 + .../origami_patterns_pleat_hypar.inx | 8 +- .../origami_patterns_template.inx | 45 +-- .../origami_patterns_waterbomb.inx | 6 +- 12 files changed, 789 insertions(+), 58 deletions(-) create mode 100644 extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Bendy_Straw.py create mode 100644 extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/SupportRing.py create mode 100644 extensions/fablabchemnitz/origami_patterns/origami_patterns_bendy_straw.inx create mode 100644 extensions/fablabchemnitz/origami_patterns/origami_patterns_misc_support_ring.inx diff --git a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Bendy_Straw.py b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Bendy_Straw.py new file mode 100644 index 00000000..9e1a4977 --- /dev/null +++ b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Bendy_Straw.py @@ -0,0 +1,369 @@ +#! /usr/bin/env python3 + +import numpy as np +from math import pi, sin, cos, tan, asin, acos, atan, sqrt + +import inkex + +from Path import Path +from Pattern import Pattern + +# Select name of class, inherits from Pattern +# TODO: +# 1) Implement __init__ method to get all custom options and then call Pattern's __init__ +# 2) Implement generate_path_tree to define all of the desired strokes +MIN = 0.0001 + + +class Bendy_Straw(Pattern): + + def __init__(self): + Pattern.__init__(self) # Must be called in order to parse common options + + # save all custom parameters defined on .inx file + self.add_argument('--pattern', default='bendy_straw') + self.add_argument('--pattern_type', default='origami') + self.add_argument('--parameter_type', default='angles') + self.add_argument('--n', type=int, default=6) + self.add_argument('--lines', type=int, default=3) + self.add_argument('--radius', type=float, default=25.0) + self.add_argument('--radial_ratio', type=float, default=0.75) + + self.add_argument('--alpha1', type=int, default=45) + self.add_argument('--alpha2', type=int, default=35) + self.add_argument('--h1', type=float, default=1) + self.add_argument('--h2', type=float, default=2) + + self.add_argument('--vertex_base_outer_bool', type=inkex.Boolean, default=False) + self.add_argument('--vertex_base_inner_bool', type=inkex.Boolean, default=False) + self.add_argument('--vertex_radius_outer_bool', type=inkex.Boolean, default=False) + self.add_argument('--vertex_radius_inner_bool', type=inkex.Boolean, default=False) + + self.add_argument('--add_attachment', type=inkex.Boolean, default=False) + + # slot options for support ring + self.add_argument('--base_height', type=float, default=5.0) + self.add_argument('--add_base_slot', type=inkex.Boolean, default=False) + self.add_argument('--center_base_slot', type=inkex.Boolean, default=False) + self.add_argument('--base_slot_height', type=float, default=3.0) + self.add_argument('--base_slot_width', type=float, default=3.0) + self.add_argument('--distance', type=float, default=3.0) + self.add_argument('--add_distance_slot', type=inkex.Boolean, default=False) + self.add_argument('--distance_slot_height', type=float, default=3.0) + self.add_argument('--distance_slot_width', type=float, default=3.0) + + def generate_path_tree(self): + """ Specialized path generation for your origami pattern + """ + # retrieve conversion factor for selected unit + unit_factor = self.calc_unit_factor() + vertex_radius = self.options.vertex_radius * unit_factor + + # retrieve saved parameters, and apply unit factor where needed + pattern_type = self.options.pattern_type + n = self.options.n + lines = self.options.lines + radial_ratio = self.options.radial_ratio + R = self.options.radius * unit_factor + distance = self.options.distance * unit_factor + base_height = self.options.base_height * unit_factor + # add_attachment = self.options.add_attachment + # attachment_length = self.options.attachment_length * unit_factor + r = R * radial_ratio + + if (self.options.parameter_type == 'angles'): + alpha1 = self.options.alpha1 * pi / 180 + alpha2 = self.options.alpha2 * pi / 180 + elif (self.options.parameter_type == 'heights'): + alpha1 = atan(self.options.h1 * unit_factor / (R - r)) + alpha2 = atan(self.options.h2 * unit_factor / (R - r)) + + # calculating pattern parameters + l1 = (R - r) / cos(alpha1) + l2 = (R - r) / cos(alpha2) + A = 2 * R * sin(pi / n) + # attachment_length = 0.01 * self.options.attachment_length * A + a = A * radial_ratio + dx = (A - a) / 2 + beta1 = acos(cos(alpha1) * sin(pi / n)) + beta2 = acos(cos(alpha2) * sin(pi / n)) + b1 = l1 * sin(beta1) + b2 = l2 * sin(beta2) + height = (b1 + b2) * lines + distance * (lines - 1) + + if self.options.add_attachment: n = n+1 + + # + # big horizontal mountains grid + # + mountain_horizontal_stroke = Path([(0, base_height), (A * n, base_height)], 'm') + horizontal_grid_mountain = [] + for i in range(1, lines): + horizontal_grid_mountain.append( + mountain_horizontal_stroke + (0, distance * (i - 1) + b1 * (i + 0) + b2 * (i + 0))) + horizontal_grid_mountain.append( + mountain_horizontal_stroke + (0, distance * (i + 0) + b1 * (i + 0) + b2 * (i + 0))) + if distance < MIN: + horizontal_grid_mountain = horizontal_grid_mountain[::2] + if base_height > MIN: + horizontal_grid_mountain.insert(0, mountain_horizontal_stroke) + horizontal_grid_mountain.append( + mountain_horizontal_stroke + (0, distance * (lines - 1) + b1 * lines + b2 * lines)) + + # reverse every other horizontal stroke for faster laser-cutting + for i in range(len(horizontal_grid_mountain)): + if (i % 2 == 0): + horizontal_grid_mountain[i].points.reverse() + + # + # diamond shapes + # + + # full diamond patterns styles, depending on pattern type + style_diag_left = 'm' + style_diag_right = 'm' + style_diag = 'v' + style_vert = 'm' + style_hori_left = 'm' + style_hori_right = 'm' + if pattern_type == 'origami' or pattern_type == 'origami_bent': + style_hori_left = 'v' + style_diag_left = 'n' + style_diag_right = 'v' + elif pattern_type == 'origami2': + style_hori_right = 'v' + style_diag_left = 'v' + style_diag_right = 'n' + elif pattern_type == 'kirigami1': + style_vert = 'v' + style_hori_left = 'c' + style_hori_right = 'c' + elif pattern_type == 'kirigami2': + style_diag_left = 'c' + style_diag_right = 'c' + style_hori_left = 'n' + style_hori_right = 'n' + style_vert = 'n' + + # diamond pattern with strokes of different styles + stroke_base = Path([(0, 0), (0, base_height)], 'm') + diamond_diagonals_left = Path([(0, base_height), (-dx, base_height + b1), (0, base_height + b1 + b2)], + style_diag_left) + diamond_diagonals_right = Path([(0, base_height + b1 + b2), (dx, base_height + b1), (0, base_height)], + style_diag_right) + diamond_vertical = Path([(0, base_height), (0, base_height + b1 + b2)], style_vert) + stroke_distance = Path([(0, base_height + b1 + b2), (0, distance + base_height + b1 + b2)], 'm') + diamond_horizontal_left = Path([(-dx, 0), (0, 0)], style_hori_left) + diamond_horizontal_right = Path([(0, 0), (dx, 0)], style_hori_right) + + diamond = [diamond_diagonals_left, diamond_diagonals_right, diamond_vertical] + + if pattern_type == 'origami_bent': + bent_diagonal = Path([(0, base_height + b1 + b2), (dx, base_height + b1), (0, base_height)], 'm') + bent_horizontal = Path([(0, 0), (dx, 0)], 'v') + line_bent = [] + + + # drawing lines with the diamond shapes + line_left = [] + line_middle = [] + line_right = [] + if base_height > MIN: + line_middle.append(stroke_base) + if pattern_type == 'origami_bent': + line_bent.append(stroke_base) + for i in range(lines): + delta = (0, (distance + b1 + b2) * i) + if pattern_type != 'kirigami2': + line_left.append(diamond_diagonals_right + delta) + line_middle = line_middle + Path.list_add(diamond, delta) + if pattern_type != 'kirigami2': + line_right.append(diamond_diagonals_left + delta) + if distance > MIN and i < lines - 1: + line_middle.append(stroke_distance + delta) + + if pattern_type == 'origami_bent': + line_bent = line_bent + [bent_diagonal + delta] + if distance > MIN and i < lines - 1: + line_bent.append(stroke_distance + delta) + + if base_height > MIN: + line_middle.append(stroke_base + (0, base_height + height)) + if pattern_type == 'origami_bent': + line_bent.append(stroke_base + (0, base_height + height)) + + # creating full diamond patterns + line_left = line_left[::-1] + diamond_patterns_full = [line_left] + for i in range(n - 1): + delta = (A * (i + 1), 0) + if pattern_type == 'origami_bent' and i == 2: + diamond_patterns_full.append(Path.list_add(line_bent, delta)) + else: + diamond_patterns_full.append(Path.list_add(line_middle, delta)) + diamond_patterns_full.append(Path.list_add(line_right, (A * n, 0))) + + # + # small horizontal alternate style grid + # + valley_points = [(dx, 0), + (dx + a, 0)] + valley_stroke = Path(valley_points, 'v') + if pattern_type == 'kirigami2': + horizontal_line = [] + else: + horizontal_line = [diamond_horizontal_right + (0, 0)] + for i in range(n): + if not (pattern_type == 'origami_bent' and i == 3): + horizontal_line.append(valley_stroke + ((a + 2 * dx) * i, 0)) + if (pattern_type != 'kirigami2'): + if not (pattern_type == 'origami_bent' and i == 3): + horizontal_line.append(diamond_horizontal_left + (A + (a + 2 * dx) * i, 0)) + if pattern_type == 'origami_bent' and i==2: + horizontal_line.append(bent_horizontal + (A + (a + 2 * dx) * i, 0)) + elif i < n - 1: + horizontal_line.append(diamond_horizontal_right + (A + (a + 2 * dx) * i, 0)) + horizontal_grid_alternate = [] + for i in range(lines): + horizontal_grid_alternate.append( + Path.list_add(horizontal_line, (0, base_height + distance * (i + 0) + b1 * (i + 1) + b2 * (i + 0)))) + + # reverse every other horizontal stroke for faster laser-cutting + for i in range(len(horizontal_grid_alternate)): + if (i % 2 == 0): + horizontal_grid_alternate[i] = Path.list_invert(horizontal_grid_alternate[i]) + + # for i in range(len(horizontal_grid_alternate)): + # inkex.debug(i) + # Path.debug_points(horizontal_grid_alternate[i]) + # inkex.debug('\n') + + # + # edge drawing + # + self.edge_points = [(0, 0)] + self.edge_points.append((A * n, 0)) + + # rectangles for attachments at base and between cells + + # add upper base attachment + self.edge_points.append((A * n, base_height)) + + # draw attachment between cells and inside cells + for i in range(lines): + self.edge_points.append((A * n + 0, base_height + (b1 + b2) * (i + 0) + distance * i)) + if pattern_type == 'kirigami2': + self.edge_points.append((A * n - dx, base_height + b1 * (i + 1) + (b2 + distance) * i)) + self.edge_points.append((A * n + 0, base_height + (b1 + b2) * (i + 1) + distance * i)) + + self.edge_points.append((A * n, height + 2 * base_height)) + self.edge_points.append((0, height + 2 * base_height)) + + # if full kirigami selected, cut left side next to cells + if pattern_type == 'kirigami2': + for i in range(lines): + self.edge_points.append((0, height + base_height - (b1 + b2) * (i + 0) - distance * i)) + self.edge_points.append((dx, height + base_height - b2 * (i + 1) - (b1 + distance) * i)) + self.edge_points.append((0, height + base_height - (b1 + b2) * (i + 1) - distance * i)) + + # + # slots drawing + # + center_slot = self.options.center_base_slot + base_slots = [] + if self.options.add_base_slot: + base_slot_height = self.options.base_slot_height + base_slot_width = self.options.base_slot_width + if base_slot_height > base_height or base_slot_width > A: + inkex.debug('Base slot dimensions are too big') + base_slot_height = min(base_height, base_slot_height) + base_slot_width = min(A, base_slot_width) + if base_slot_height > 0 and base_slot_width > 0: + points = [(0, 0), + (0, base_slot_height), + (base_slot_width, base_slot_height), + (base_slot_width, 0,)] + base_slot = Path(points, 'c', closed=True) + ((A - base_slot_width)/2, (base_height - base_slot_height)/(1+center_slot)) + base_slots_line = [] + for i in range(n): + base_slots_line.append(base_slot + (A*i, 0)) + base_slots = [base_slots_line] + base_slots.append(Path.list_add(base_slots_line, (0, height+base_slot_height + (base_height - base_slot_height)*center_slot))) + + dist_slots = [] + if self.options.add_distance_slot: + dist_slot_height = self.options.distance_slot_height + dist_slot_width = self.options.distance_slot_width + if dist_slot_height > distance or dist_slot_width > A: + inkex.debug('Dimensions of slots between cells are too big') + dist_slot_height = min(distance, dist_slot_height) + dist_slot_width = min(A, dist_slot_width) + + if dist_slot_height > 0 and dist_slot_width > 0: + points = [(0, 0), + (0, dist_slot_height), + (dist_slot_width, dist_slot_height), + (dist_slot_width, 0,)] + dist_slot = Path(points, 'c', closed=True) + ((A - dist_slot_width)/2, base_height+b1+b2 + (distance - dist_slot_height)/2) + dist_slots_line = [] + for i in range(n): + dist_slots_line.append(dist_slot + (A*i, 0)) + + for i in range(lines-1): + dist_slots.append(Path.list_add(dist_slots_line, (0, i*(b1+b2+distance)))) + + + + # sending lines to draw + self.path_tree = [horizontal_grid_mountain, horizontal_grid_alternate, diamond_patterns_full, base_slots, dist_slots] + + # + # vertices drawing + # + # outer base vertices? + if self.options.vertex_base_outer_bool: + self.vertex_points = self.vertex_points + [(A * i, height + base_height * 2) for i in range(n + 1)] + self.vertex_points = self.vertex_points + [(A*i, 0) for i in range(n+1)] + + # inner base vertices? + if self.options.vertex_base_inner_bool: + self.vertex_points = self.vertex_points + [(A*i, base_height) for i in range(n+1)] + self.vertex_points = self.vertex_points + [(A*i, height+base_height) for i in range(n+1)] + for j in range(lines-1): + self.vertex_points = self.vertex_points + [(A*i, base_height+((b1+b2)*(j+1))+distance*j) for i in range(n+1)] + \ + [(A*i, base_height+((b1+b2)*(j+1))+distance*(j+1)) for i in range(n+1)] + + # radius vertices? + if self.options.vertex_radius_outer_bool and pattern_type != 'kirigami2': + for j in range(lines): + i_range = list(range(3)) + list(range(3+(pattern_type=='origami_bent'), n + 1)) + self.vertex_points = self.vertex_points + [(A * i, base_height + b1*(j+1) + (b2+distance)*j) for i in i_range] + if self.options.vertex_radius_inner_bool: + for j in range(lines): + if pattern_type != 'origami2': + # pass + self.vertex_points = self.vertex_points + [(dx + A * i, base_height + b1*(j+1) + (b2+distance)*j) for i in range(n)] + if pattern_type[:7] != 'origami': + # pass + self.vertex_points = self.vertex_points + [(-dx + A * (i + 1), base_height + b1 * (j + 1) + (b2 + distance) * j) for i in range(n)] + # for j in range(lines): + + + + + # self.vertex_points = self.vertex_points + vertices_base + + # self.vertex_points = self.vertex_points + self.edge_points + # diamond_patterns_full_simple = Path.list_simplify(diamond_patterns_full) + # for path in diamond_patterns_full: + # # path = Path.list_simplify(path) + # # path = Path.list_simplify(path[0]) + # if path.style != 'n': + # self.vertex_points = self.vertex_points + path.points + + + +# + +if __name__ == '__main__': + Bendy_Straw().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Kresling_full.py b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Kresling_full.py index 5d55d004..8a3d9b3b 100644 --- a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Kresling_full.py +++ b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Kresling_full.py @@ -10,8 +10,6 @@ from Kresling import Kresling class Kresling_Full(Kresling): def __init__(self): - """ Constructor - """ Kresling.__init__(self) # Must be called in order to parse common options self.add_argument('--measure_value', type=float, default=10.0, help="Length") diff --git a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Path.py b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Path.py index ceab873c..a9cf8aca 100644 --- a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Path.py +++ b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Path.py @@ -1,9 +1,35 @@ #! /usr/bin/env python3 -import inkex -from lxml import etree +""" +Path Class + +Defines a path and what it is supposed to be (mountain, valley, edge) + +""" + +import inkex # Required +import simplestyle # will be needed here for styles support + +# compatibility hack +try: + from lxml import etree + inkex.etree = etree +except: + pass + from math import sin, cos, pi +# compatibility hack for formatStyle +def format_style(style): + try: + return str(inkex.Style(style)) # new + except: + return simplestyle.formatStyle(style) # old +# def format_style(style): + # return simplestyle.formatStyle(style) + + + class Path: """ Class that defines an svg stroke to be drawn in Inkscape @@ -47,6 +73,7 @@ class Path: of the style. Ex.: if path_tree[i].style = 'm', styles_dict must have an element 'm'. + generate_hgrid(cls, xlims, ylims, nb_of_divisions, style, include_edge=False) Generate list of Path instances, in which each Path is a stroke defining a horizontal grid dividing the space xlims * ylims nb_of_divisions times. @@ -70,8 +97,16 @@ class Path: list_add(cls, paths, offsets) Generate list of new Path instances, adding a different tuple for each list + + list_simplify(cls, paths) + Gets complicated path-tree list and converts it into + a simple list. + list_invert(cls, paths) + Invert list of paths and points of each path. + debug_points(cls, paths): + Plots points of path tree in drawing order. """ def __init__(self, points, style, closed=False, invert=False, radius=0.1, separated=False): @@ -126,7 +161,7 @@ class Path: - Draws strokes defined on "path_tree" to "group" - Inputs: -- path_tree [nested list] of Path instances - -- group [etree.SubElement] + -- group [inkex.etree.SubElement] -- styles_dict [dict] containing all styles for path_tree """ @staticmethod @@ -138,10 +173,11 @@ class Path: if len(subpath) == 1: subgroup = group else: - subgroup = etree.SubElement(group, 'g') + subgroup = inkex.etree.SubElement(group, 'g') Path.draw_paths_recursively(subpath, subgroup, styles_dict) else: - if styles_dict[subpath.style]['draw']: + # ~ if subpath.style != 'n': + if subpath.style != 'n' and styles_dict[subpath.style]['draw']: if subpath.type == 'linear': points = subpath.points @@ -151,13 +187,14 @@ class Path: if subpath.closed: path = path + 'L{},{} Z'.format(*points[0]) - attribs = {'style': str(inkex.Style(styles_dict[subpath.style])), 'd': path} - etree.SubElement(group, inkex.addNS('path', 'svg'), attribs) + + attribs = {'style': format_style(styles_dict[subpath.style]), 'd': path} + inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), attribs) else: - attribs = {'style': str(inkex.Style(styles_dict[subpath.style])), + attribs = {'style': format_style(styles_dict[subpath.style]), 'cx': str(subpath.points[0][0]), 'cy': str(subpath.points[0][1]), 'r': str(subpath.radius)} - etree.SubElement(group, inkex.addNS('circle', 'svg'), attribs) + inkex.etree.SubElement(group, inkex.addNS('circle', 'svg'), attribs) @classmethod def generate_hgrid(cls, xlims, ylims, nb_of_divisions, style, include_edge=False): @@ -242,6 +279,7 @@ class Path: paths.append(cls([points[i], points[j]], styles[i])) return paths + def __add__(self, offsets): """ " + " operator overload. @@ -463,4 +501,60 @@ class Path: for path in paths: paths_new.append(Path.reflect(path, p1, p2)) - return paths_new \ No newline at end of file + return paths_new + + @classmethod + def list_simplify(cls, paths): + """ Gets complicated path-tree list and converts it into + a simple list. + + Returns + --------- + paths: list + list of Path instances + """ + if type(paths) == Path: + return paths + + simple_list = [] + for i in range(len(paths)): + if type(paths[i]) == Path: + simple_list.append(paths[i]) + elif type(paths[i]) == list: + simple_list = simple_list + Path.list_simplify(paths[i]) + return simple_list + + @classmethod + def list_invert(cls, paths): + """ Invert list of paths and points of each path. + + Returns + --------- + paths: list + list of Path instances + """ + + if type(paths) == Path: + # return Path(paths.points[::-1], paths.style, paths.closed, paths.invert) + return Path(paths.points, paths.style, paths.closed, True) + elif type(paths) == list: + paths_inverted = [] + # n = len(paths) + # for i in range(n): + # # paths_inverted.append(Path.list_invert(paths[n-1-i])) + # paths_inverted.append(Path.list_invert(paths[i])) + for path in paths: + # paths_inverted.append(Path.list_invert(paths[n-1-i])) + paths_inverted.append(Path.list_invert(path)) + return paths_inverted[::-1] + + @classmethod + def debug_points(cls, paths): + """ Plots points of path tree in drawing order. + + """ + if type(paths) == Path: + inkex.debug(paths.points) + elif type(paths) == list: + for sub_path in paths: + Path.debug_points(sub_path) diff --git a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Pattern.py b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Pattern.py index 3dc8c257..199a06ff 100644 --- a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Pattern.py +++ b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/Pattern.py @@ -29,7 +29,8 @@ class Pattern(inkex.Effect): self.add_argument('--mountain_dashes_duty', type=float, default=0.5, help='Mountain dash duty cycle.') self.add_argument('--mountain_dashes_bool', type=inkex.Boolean, default=True, help='Dashed strokes?') self.add_argument('--mountain_bool', type=inkex.Boolean, default=True, help='Draw mountains?') - + self.add_argument('--mountain_bool_only', type=inkex.Boolean, default=False) + # -------------------------------------------------------------------------------------------------------------- # valley options self.add_argument('-v', '--valley_stroke_color', default=65535, help='The valley creases color.') @@ -38,6 +39,7 @@ class Pattern(inkex.Effect): self.add_argument('--valley_dashes_duty', type=float, default=0.25, help='Valley dash duty cycle.') self.add_argument('--valley_dashes_bool', type=inkex.Boolean, default=True, help='Dashed strokes?') self.add_argument('--valley_bool', type=inkex.Boolean, default=True, help='Draw valleys?') + self.add_argument('--valley_bool_only', type=inkex.Boolean, default=False) # -------------------------------------------------------------------------------------------------------------- # edge options @@ -47,6 +49,7 @@ class Pattern(inkex.Effect): self.add_argument('--edge_dashes_duty', type=float, default=0.25, help='Edge dash duty cycle.') self.add_argument('--edge_dashes_bool', type=inkex.Boolean, default=False, help='Dashed strokes?') self.add_argument('--edge_bool', type=inkex.Boolean, default=True, help='Draw edges?') + self.add_argument('--edge_bool_only', type=inkex.Boolean, default=False) self.add_argument('--edge_single_path', type=inkex.Boolean, default=True, help='Edges as single path?') # -------------------------------------------------------------------------------------------------------------- @@ -57,6 +60,7 @@ class Pattern(inkex.Effect): self.add_argument('--universal_dashes_duty', type=float, default=0.25, help='Universal dash duty cycle.') self.add_argument('--universal_dashes_bool', type=inkex.Boolean, default=False, help='Dashed strokes?') self.add_argument('--universal_bool', type=inkex.Boolean, default=True, help='Draw universal creases?') + self.add_argument('--universal_bool_only', type=inkex.Boolean, default=False) # -------------------------------------------------------------------------------------------------------------- # semicrease options @@ -66,7 +70,8 @@ class Pattern(inkex.Effect): self.add_argument('--semicrease_dashes_duty', type=float,default=0.25, help='Semicrease dash duty cycle.') self.add_argument('--semicrease_dashes_bool', type=inkex.Boolean, default=False, help='Dashed strokes?') self.add_argument('--semicrease_bool', type=inkex.Boolean, default=True, help='Draw semicreases?') - + self.add_argument('--semicrease_bool_only', type=inkex.Boolean, default=False) + # -------------------------------------------------------------------------------------------------------------- # cut options self.add_argument('--cut_stroke_color', default=16711935, help='The cut creases color.') @@ -75,23 +80,42 @@ class Pattern(inkex.Effect): self.add_argument('--cut_dashes_duty', type=float, default=0.25, help='Cut dash duty cycle.') self.add_argument('--cut_dashes_bool', type=inkex.Boolean, default=False, help='Dashed strokes?') self.add_argument('--cut_bool', type=inkex.Boolean, default=True, help='Draw cuts?') + self.add_argument('--cut_bool_only', type=inkex.Boolean, default=False) # -------------------------------------------------------------------------------------------------------------- # vertex options self.add_argument('--vertex_stroke_color', default=255, help='Vertices\' color.') self.add_argument('--vertex_stroke_width', type=float, default=0.1, help='Width of vertex strokes.') self.add_argument('--vertex_radius', type=float, default=0.1, help='Radius of vertices.') - self.add_argument('--vertex_bool', type=inkex.Boolean, default=True, help='Draw vertices?') + self.add_argument('--vertex_bool', type=inkex.Boolean, default=True) + self.add_argument('--vertex_bool_only', type=inkex.Boolean, default=False) + # here so we can have tabs - but we do not use it directly - else error self.add_argument('--active-tab', default='title', help="Active tab.") self.path_tree = [] self.edge_points = [] + self.vertex_points = [] self.translate = (0, 0) def effect(self): - """ Main function, called when the extension is run. - """ + # check if any selected to print only some of the crease types: + bool_only_list = [self.options.mountain_bool_only, + self.options.valley_bool_only, + self.options.edge_bool_only, + self.options.universal_bool_only, + self.options.semicrease_bool_only, + self.options.cut_bool_only, + self.options.vertex_bool_only] + if sum(bool_only_list) > 0: + self.options.mountain_bool = self.options.mountain_bool and self.options.mountain_bool_only + self.options.valley_bool = self.options.valley_bool and self.options.valley_bool_only + self.options.edge_bool = self.options.edge_bool and self.options.edge_bool_only + self.options.universal_bool = self.options.universal_bool and self.options.universal_bool_only + self.options.semicrease_bool = self.options.semicrease_bool and self.options.semicrease_bool_only + self.options.cut_bool = self.options.cut_bool and self.options.cut_bool_only + self.options.vertex_bool = self.options.vertex_bool and self.options.vertex_bool_only + # construct dictionary containing styles self.create_styles_dict() @@ -103,6 +127,14 @@ class Pattern(inkex.Effect): # what page are we on # page_id = self.options.active_tab # sometimes wrong the very first time + # get vertex points and add them to path tree + vertex_radius = self.options.vertex_radius * self.calc_unit_factor() + vertices = [] + self.vertex_points = list(set([i for i in self.vertex_points])) # remove duplicates + for vertex_point in self.vertex_points: + vertices.append(Path(vertex_point, style='p', radius=vertex_radius)) + self.path_tree.append(vertices) + # Translate according to translate attribute g_attribs = {inkex.addNS('label', 'inkscape'): '{} Origami pattern'.format(self.options.pattern), # inkex.addNS('transform-center-x','inkscape'): str(-bbox_center[0]), diff --git a/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/SupportRing.py b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/SupportRing.py new file mode 100644 index 00000000..f933fe62 --- /dev/null +++ b/extensions/fablabchemnitz/origami_patterns/OrigamiPatterns/SupportRing.py @@ -0,0 +1,86 @@ +#! /usr/bin/env python3 + +import numpy as np +from math import pi, sin, cos + +import inkex + +from Path import Path +from Pattern import Pattern + +class SupportRing(Pattern): + + def __init__(self): + Pattern.__init__(self) # Must be called in order to parse common options + + # save all custom parameters defined on .inx file + self.add_argument('--sides', type=int, default=3) + self.add_argument('--radius_external', type=float, default=10.0) + self.add_argument('--radius_ratio', type=float, default=0.5) + self.add_argument('--radius_type', default='polygonal') + self.add_argument('--radius_draw', type=inkex.Boolean, default=True) + self.add_argument('--connector_length', type=float, default=3.0) + self.add_argument('--connector_thickness', type=float, default=3.0) + self.add_argument('--head_length', type=float, default=1.0) + self.add_argument('--head_thickness', type=float, default=1.0) + self.add_argument('--pattern', default='support ring') + + def generate_path_tree(self): + """ Specialized path generation for your origami pattern + """ + # retrieve conversion factor for selected unit + unit_factor = self.calc_unit_factor() + + # retrieve saved parameters, and apply unit factor where needed + radius_external = self.options.radius_external * unit_factor + radius_type = self.options.radius_type + radius_ratio = self.options.radius_ratio + radius_internal = radius_external * radius_ratio + dradius = radius_external-radius_internal + sides = self.options.sides + connector_length = self.options.connector_length * unit_factor + connector_thickness = self.options.connector_thickness * unit_factor + head_length = self.options.head_length * unit_factor + head_thickness = self.options.head_thickness * unit_factor + + angle = pi / sides + length_external = 2 * radius_external * sin(angle) + length_internal = length_external * radius_ratio + + external_points = [(-length_external/2, 0), + (-connector_thickness / 2, 0), + (-connector_thickness / 2, -connector_length), + (-connector_thickness / 2 - head_thickness / 2, -connector_length), + (-connector_thickness / 2, -connector_length - head_length), + (0, -connector_length - head_length), + (+connector_thickness / 2, -connector_length - head_length), + (+connector_thickness / 2 + head_thickness / 2, -connector_length), + (+connector_thickness / 2, -connector_length), + (+connector_thickness / 2, 0), + (length_external/2, 0)] + internal_points = [(0, 0), (length_internal, 0)] + + external_lines_0 = Path(external_points, 'm') + (length_external / 2, 0) + external_lines = [external_lines_0] + + for i in range(sides-1): + x, y = external_lines[-1].points[-1] + external_lines.append(external_lines_0*(1, 2*(i+1)*angle) + (x, y)) + + self.path_tree = [external_lines] + + if self.options.radius_draw == True: + if radius_type == 'polygonal': + internal_lines_0 = Path(internal_points, 'm') + internal_lines = [internal_lines_0] + for i in range(sides - 1): + x, y = internal_lines[-1].points[-1] + internal_lines.append(internal_lines_0*(1, 2*(i+1)*angle) + (x, y)) + internal_lines = Path.list_add(internal_lines, ((length_external - length_internal) / 2, dradius * cos(angle))) + elif radius_type == 'circular': + internal_lines = Path((length_external / 2, radius_internal + dradius/2), radius=radius_internal, style = 'm') + + self.path_tree.append(internal_lines) + +if __name__ == '__main__': + SupportRing().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_bendy_straw.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_bendy_straw.inx new file mode 100644 index 00000000..97d80474 --- /dev/null +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_bendy_straw.inx @@ -0,0 +1,105 @@ + + + Origami Pattern - Bendy Straw + fablabchemnitz.de.origami_patterns.bendy_straw + + + + + + + + + + 6 + 3 + + 25.0 + 0.75 + + + + + + 45 + 35 + 1 + 2 + + + + + + + + + + false + + 5.0 + false + false + 3.0 + 3.0 + + 3.0 + false + 3.0 + 3.0 + + + true + true + 1 + 0.5 + 0.1 + 4278190335 + + + true + true + 1 + 0.25 + 0.1 + 65535 + + + true + false + 1 + 0.25 + 0.1 + 16711935 + + + true + true + false + 1 + 0.25 + 0.1 + 255 + + + true + true + true + true + true + 0.1 + 0.1 + 255 + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_kresling.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_kresling.inx index e742e297..c2b253c7 100644 --- a/extensions/fablabchemnitz/origami_patterns/origami_patterns_kresling.inx +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_kresling.inx @@ -1,6 +1,6 @@ - Origami Pattern - Kresling tower + Origami Pattern - Kresling Tower fablabchemnitz.de.origami_patterns.kresling_full @@ -21,9 +21,6 @@ - @@ -48,6 +45,7 @@ true + false true 1 0.5 @@ -56,6 +54,7 @@ true + false true 1 0.25 @@ -64,6 +63,7 @@ true + false true false 1 @@ -72,7 +72,8 @@ 255 - false + true + false 0.1 0.1 255 diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_misc_support_ring.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_misc_support_ring.inx new file mode 100644 index 00000000..ec1c8443 --- /dev/null +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_misc_support_ring.inx @@ -0,0 +1,48 @@ + + + Origami Pattern - Support Ring + fablabchemnitz.de.origami_patterns.support_ring + + + 6 + 10.0 + + 3.0 + 3.0 + 1.0 + 1.0 + + true + 0.5 + + + + + + + + + + + + + + false + 1 + 0.5 + 0.1 + 4278190335 + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_circular.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_circular.inx index ffcbf00a..84c1ae9a 100644 --- a/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_circular.inx +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_circular.inx @@ -20,6 +20,7 @@ true + false true 1 0.5 @@ -28,6 +29,7 @@ true + false true 1 0.25 @@ -36,6 +38,7 @@ true + false true false 1 @@ -43,8 +46,16 @@ 0.1 255 + + true + false + 0.1 + 0.1 + 255 + true + false false 1 0.25 diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_hypar.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_hypar.inx index ebfec933..f4d8139c 100644 --- a/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_hypar.inx +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_pleat_hypar.inx @@ -21,10 +21,10 @@ 7 false - true + false true 1 0.5 @@ -33,6 +33,7 @@ true + false true 1 0.25 @@ -41,6 +42,7 @@ true + false false 1 0.25 @@ -49,6 +51,7 @@ true + false true false 1 @@ -57,7 +60,8 @@ 255 - false + true + false 0.1 0.1 255 diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_template.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_template.inx index fc3d7c57..eba5068f 100644 --- a/extensions/fablabchemnitz/origami_patterns/origami_patterns_template.inx +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_template.inx @@ -1,6 +1,6 @@ - Origami Pattern - Template effect + Origami Pattern - Template Effect fablabchemnitz.de.origami_patterns.template @@ -21,14 +21,16 @@ true + false true - 1 - 0.5 + 1 + 0.5 0.1 4278190335 true + false true 1 0.25 @@ -37,44 +39,21 @@ true + false true false - 1 - 0.25 - 0.1 + 1 + 0.25 + 0.1 255 true - 0.1 - 0.1 + false + 0.1 + 0.1 255 - - - - - - - - - - - - - - - - - - - - - - - - - all diff --git a/extensions/fablabchemnitz/origami_patterns/origami_patterns_waterbomb.inx b/extensions/fablabchemnitz/origami_patterns/origami_patterns_waterbomb.inx index b54314e0..d24e9971 100644 --- a/extensions/fablabchemnitz/origami_patterns/origami_patterns_waterbomb.inx +++ b/extensions/fablabchemnitz/origami_patterns/origami_patterns_waterbomb.inx @@ -28,6 +28,7 @@ true + false true 1 0.5 @@ -36,6 +37,7 @@ true + false true 1 0.25 @@ -44,6 +46,7 @@ true + false true false 1 @@ -52,7 +55,8 @@ 255 - false + true + false 0.1 0.1 255