#! /usr/bin/env python3 from math import pi, sin, cos, tan, acos, sqrt import inkex from Path import Path from Pattern import Pattern class Kresling(Pattern): def __init__(self): Pattern.__init__(self) # Must be called in order to parse common options self.add_argument("-p", "--pattern", default="kresling", help="Origami pattern") self.add_argument("--lines", type=int, default=1, help="Number of lines") self.add_argument("--sides", type=int, default=3, help="Number of polygon sides") self.add_argument("--add_attachment", type=inkex.Boolean, default=False, help="Add attachment?") self.add_argument("--attachment_percentage", type=float, default=100., help="Length percentage of extra facet") self.add_argument("--mirror_cells", type=inkex.Boolean, default=False, help="Mirror odd cells?") @staticmethod def generate_kresling_zigzag(sides, radius, angle_ratio, add_attachment): theta = (pi / 2.) * (1 - 2. / sides) l = 2. * radius * cos(theta * (1. - angle_ratio)) a = 2. * radius * sin(pi / sides) # b = sqrt(a * a + l * l - 2 * a * l * cos(angle_ratio * theta)) # phi = abs(acos((l * l + b * b - a * a) / (2 * l * b))) # gamma = pi / 2 - angle_ratio * theta - phi dy = l * sin(theta * angle_ratio) dx = l * cos(theta * angle_ratio) - a points = [] styles = [] for i in range(sides): points.append((i * a, 0)) points.append(((i + 1) * a + dx, -dy)) styles.append('v') if i != sides - 1: styles.append('m') elif add_attachment: points.append((sides * a, 0)) styles.append('m') path = Path.generate_separated_paths(points, styles) return path def generate_path_tree(self): """ Specialized path generation for Waterbomb tesselation pattern """ unit_factor = self.calc_unit_factor() vertex_radius = self.options.vertex_radius * unit_factor lines = self.options.lines sides = self.options.sides radius = self.options.radius * unit_factor angle_ratio = self.options.angle_ratio mirror_cells = self.options.mirror_cells theta = (pi/2.)*(1 - 2./sides) l = 2.*radius*cos(theta*(1.-angle_ratio)) a = 2.*radius*sin(pi/sides) # b = sqrt(a*a + l*l - 2*a*l*cos(angle_ratio*theta)) # phi = abs(acos((l*l + b*b - a*a)/(2*l*b))) # gamma = pi/2 - angle_ratio*theta - phi # dy = b*cos(gamma) # dx = b*sin(gamma) dy = l * sin(theta * angle_ratio) dx = l * cos(theta * angle_ratio) - a add_attachment = self.options.add_attachment attachment_percentage = self.options.attachment_percentage/100. attachment_height = a*(attachment_percentage-1)*tan(angle_ratio*theta) vertices = [] for i in range(sides + 1): for j in range(lines + 1): if mirror_cells: vertices.append(Path((dx*((lines - j)%2) + a*i, dy*j), style='p', radius=vertex_radius)) else: vertices.append(Path((dx*(lines - j) + a*i, dy*j), style='p', radius=vertex_radius)) # create a horizontal grid, then offset each line according to angle grid_h = Path.generate_hgrid([0, a * sides], [0, dy * lines], lines, 'm') if not mirror_cells: # shift every mountain line of the grid to the right by increasing amounts grid_h = Path.list_add(grid_h, [(i * dx, 0) for i in range(lines - 1, 0, -1)]) else: # shift every OTHER mountain line of the grid a bit to the right grid_h = Path.list_add(grid_h, [((i%2)*dx, 0) for i in range(lines-1, 0, -1)]) if add_attachment: for i in range(lines%2, lines-1, 2): # hacky solution, changes length of every other mountain line grid_h[i].points[1-i%2] = (grid_h[i].points[1-i%2][0] + a*attachment_percentage, grid_h[i].points[1-i%2][1]) # create MV zigzag for Kresling pattern zigzag = Kresling.generate_kresling_zigzag(sides, radius, angle_ratio, add_attachment) zigzags = [] # duplicate zigzag pattern for desired number of cells if not mirror_cells: for i in range(lines): zigzags.append(Path.list_add(zigzag, (i * dx, (lines - i) * dy))) else: zigzag_mirror = Path.list_reflect(zigzag, (0, lines * dy / 2), (dx, lines * dy / 2)) for i in range(lines): if i % 2 == 1: zigzags.append(Path.list_add(zigzag_mirror, (0, -(lines - i + (lines-1)%2) * dy))) else: zigzags.append(Path.list_add(zigzag, (0, (lines - i) * dy))) # create edge strokes if not mirror_cells: self.edge_points = [ (a * sides , dy * lines), # bottom right (0 , dy * lines), # bottom left (dx * lines , 0), # top left (dx * lines + a * sides, 0)] # top right if add_attachment: for i in range(lines): x = dx * (lines - i) + a * (sides + attachment_percentage) self.edge_points.append((x, dy * i)) self.edge_points.append((x, dy * i - attachment_height)) if i != lines - 1: self.edge_points.append((x-dx-a*attachment_percentage, dy * (i + 1))) pass else: self.edge_points = [(a * sides + (lines % 2)*dx, 0)] for i in range(lines+1): self.edge_points.append([((lines+i) % 2)*dx, dy*i]) self.edge_points.append([a * sides + ((lines+i) %2)*dx, lines*dy]) if add_attachment: for i in range(lines + 1): if not i%2 == 0: self.edge_points.append([a*sides + (i%2)*(dx+a*attachment_percentage), dy*(lines - i) - (i%2)*attachment_height]) self.edge_points.append([a*sides + (i%2)*(dx+a*attachment_percentage), dy*(lines - i)]) if (i != lines): self.edge_points.append([a * sides + (i % 2) * (dx + a * attachment_percentage), dy * (lines - i) + (i % 2) * attachment_height]) else: self.edge_points.append([a * sides + (i % 2) * (dx + a * attachment_percentage), dy * (lines - i)]) else: for i in range(lines + 1): self.edge_points.append([a*sides + (i%2)*dx, dy*(lines - i)]) self.path_tree = [grid_h, zigzags, vertices] if __name__ == '__main__': Kresling().run()