154 lines
6.8 KiB
Python
154 lines
6.8 KiB
Python
#! /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() |