some fixes

This commit is contained in:
Mario Voigt 2022-11-14 23:27:13 +01:00
parent b255672418
commit 2c84a21c64
38 changed files with 5361 additions and 7 deletions

View File

@ -7,13 +7,13 @@
<option value="path_slantselection">Slant selection</option>
</param>
<label>Unit for lengths is px</label>
<param name="len1" type="float" gui-text="Len1: red &lt;" min="1" max="100">12</param>
<param name="len2" type="float" gui-text="Len2: green &lt; =" min="1" max="100">25</param>
<param name="len3" type="float" gui-text="Len3: greenyellow &lt; =" min="1" max="100">40</param>
<param name="len4" type="float" gui-text="Len4: skyblue &lt; =" min="1" max="100">60</param>
<param name="len5" type="float" gui-text="Len5: blue &gt;" min="1" max="100">60</param>
<param name="hor" type="float" gui-text="hor: red &lt; (H/W)" min="0.01" max="100">0.1</param>
<param name="ver" type="float" gui-text="ver: blue &gt;" min="1" max="100">10</param>
<param name="len1" type="float" gui-text="Len1: red &lt;" min="1" max="99999">12</param>
<param name="len2" type="float" gui-text="Len2: green &lt; =" min="1" max="99999">25</param>
<param name="len3" type="float" gui-text="Len3: greenyellow &lt; =" min="1" max="99999">40</param>
<param name="len4" type="float" gui-text="Len4: skyblue &lt; =" min="1" max="99999">60</param>
<param name="len5" type="float" gui-text="Len5: blue &gt;" min="1" max="99999">60</param>
<param name="hor" type="float" gui-text="hor: red &lt; (H/W)" min="0.01" max="99999">0.1</param>
<param name="ver" type="float" gui-text="ver: blue &gt;" min="1" max="99999">10</param>
<effect>
<object-type>path</object-type>
<effects-menu>

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>J Tech Photonics Laser Tool</name>
<id>fablabchemnitz.de.j_tech_photonics_laser_tool</id>
<param name="tabs" type="notebook">
<page name="important_settings" gui-text="Important Settings">
<param name="unit" type="optiongroup" appearance="combo" gui-text="Unit of Measurement">
<option value="mm">millimeters</option>
<option value="in">inches</option>
</param>
<param name="travel_speed" type="float" min="0" max="999999" gui-text="Travel Speed (unit/min)">3000</param>
<param name="cutting_speed" type="float" min="0" max="999999" gui-text="Cutting Speed (unit/min)">750</param>
<spacer/>
<param name="passes" type="int" min="1" max="999999" gui-text="Passes">1</param>
<param name="pass_depth" type="float" min="0" max="999999" gui-text="Pass Depth (unit)">1</param>
<spacer/>
<param name="directory" type="path" gui-text="Output Directory" mode="folder">-- Choose Output Directory --</param>
<param name="filename" type="string" gui-text="Filename">output.gcode</param>
<param name="filename_dynamic" type="bool" gui-text="Reuse SVG filename for output">false</param>
<param name="filename_suffix" type="bool" gui-text="Add Numeric Suffix to Filename">true</param>
</page>
<page name="advanced_settings" gui-text="Advanced Settings">
<param name="tool_power_command" type="string" gui-text="Tool Power Command">M3 S255;</param>
<param name="tool_off_command" type="string" gui-text="Tool Off Command">M5;</param>
<param name="dwell_time" type="float" gui-text="Dwell Time Before Moving (ms)">0</param>
<spacer/>
<param name="draw_debug" type="bool" gui-text="Draw Debug">true</param>
<param name="debug_line_width" type="float" gui-text="Debug Line Width (px)">0.5</param>
<param name="debug_arrow_scale" type="float" min="0" gui-text="Debug Arrow Scale">1.0</param>
<spacer/>
<param name="approximation_tolerance" type="string" gui-text="Approximation Tolerance (+-unit) [tip, stay between 10^-4 and 1]">0.01</param>
</page>
<page name="header_footer_settings" gui-text="Custom Header and Footer">
<spacer/>
<param name="header_path" type="path" mode="file" gui-text="Custom G-code Header Filepath" />
<param name="footer_path" type="path" mode="file" gui-text="Custom G-code Footer Filepath" />
<spacer/>
<param name="do_z_axis_start" type="bool" gui-text="Set Z-Axis Start Position">false</param>
<param name="z_axis_start" type="float" min="0" max="999999" gui-text="Absolute Z-Axis Start Position (unit)">0</param>
<spacer/>
<param name="move_to_origin_end" type="bool" gui-text="Move To Origin When Done">false</param>
<spacer/>
<param name="do_laser_off_start" type="bool" gui-text="Turn Laser Off Before a Job">true</param>
<param name="do_laser_off_end" type="bool" gui-text="Turn Laser Off After a Job">true</param>
</page>
<page name="scaling" gui-text="Coordinate System and Transformations">
<param name="machine_origin" type="optiongroup" appearance="combo" gui-text="Machine Origin">
<option value="bottom-left">bottom-left</option>
<option value="center">center</option>
<option value="top-left">top-left</option>
</param>
<param name="invert_y_axis" type="bool" gui-text="Invert Y-Axis">false</param>
<param name="bed_width" type="float" min="0" max="999999" gui-text="Bed X Width (unit)">200</param>
<param name="bed_height" type="float" min="0" max="999999" gui-text="Bed Y Length (unit)">200</param>
<spacer/>
<param name="horizontal_offset" type="float" min="-999999" max="999999" gui-text="Gcode X Offset (unit)">0</param>
<param name="vertical_offset" type="float" min="-999999" max="999999" gui-text="Gcode Y Offset (unit)">0</param>
<param name="scaling_factor" type="float" min="-999999" max="999999" gui-text="Gcode Scaling Factor">1</param>
</page>
</param>
<effect>
<object-type>path</object-type>
<effects-menu>
<submenu name="FabLab Chemnitz">
<submenu name="Import/Export/Transfer"/>
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">j_tech_photonics_laser_tool.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,312 @@
#!/usr/bin/env python3
import os
from lxml import etree
from xml.etree import ElementTree as xml_tree
from inkex import EffectExtension, Boolean
from svg_to_gcode.svg_parser import parse_root, Transformation, debug_methods
from svg_to_gcode.geometry import LineSegmentChain
from svg_to_gcode.compiler import Compiler, interfaces
from svg_to_gcode import TOLERANCES
svg_name_space = "http://www.w3.org/2000/svg"
inkscape_name_space = "http://www.inkscape.org/namespaces/inkscape"
sodipodi_name_space = "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
inx_filename = "j_tech_photonics_laser_tool.inx"
def generate_custom_interface(laser_off_command, laser_power_command):
"""Wrapper function for generating a Gcode interface with a custom laser power command"""
class CustomInterface(interfaces.Gcode):
"""A Gcode interface with a custom laser power command"""
def __init__(self):
super().__init__()
def laser_off(self):
return f"{laser_off_command}"
def set_laser_power(self, _):
return f"{laser_power_command}"
return CustomInterface
class JTechPhotonicsLaserTool(EffectExtension):
"""Inkscape Effect Extension."""
def __init__(self):
EffectExtension.__init__(self)
def effect(self):
"""Takes the SVG from Inkscape, generates gcode, returns the SVG after adding debug lines."""
root = self.document.getroot()
# Change svg_to_gcode's approximation tolerance
TOLERANCES["approximation"] = float(self.options.approximation_tolerance.replace(',', '.'))
try:
assert os.path.isdir(self.options.directory)
except:
self.debug(f"{self.options.directory} is not a directory")
exit(2)
# Construct output path
if self.options.filename:
filename = self.options.filename
if '.' not in filename:
filename += ".gcode"
elif self.document_path():
filename, extension = self.document_path().split('.')
filename = filename.split('/')[-1] + '.gcode'
else:
filename = "untitled.gcode"
output_path = os.path.join(self.options.directory, filename)
if self.options.filename_suffix:
filename, extension = output_path.split('.')
n = 1
while os.path.isfile(output_path):
output_path = filename + str(n) + '.' + extension
n += 1
# Load header and footer files
header = []
if self.options.header_path is not None:
if os.path.isfile(self.options.header_path):
with open(self.options.header_path, 'r') as header_file:
header = header_file.read().splitlines()
elif self.options.header_path != os.getcwd(): # The Inkscape file selector defaults to the working directory
self.debug(f"Header file does not exist at {self.options.header_path}")
exit(2)
footer = []
if self.options.footer_path is not None:
if os.path.isfile(self.options.footer_path):
with open(self.options.footer_path, 'r') as footer_file:
footer = footer_file.read().splitlines()
elif self.options.footer_path != os.getcwd():
self.debug(f"Footer file does not exist at {self.options.footer_path}")
exit(2)
# Customize header/footer
custom_interface = generate_custom_interface(self.options.tool_off_command, self.options.tool_power_command)
interface_instance = custom_interface()
if self.options.do_laser_off_start:
header.append(interface_instance.laser_off())
if self.options.do_laser_off_end:
footer.append(interface_instance.laser_off())
header.append(interface_instance.set_movement_speed(self.options.travel_speed))
if self.options.do_z_axis_start:
header.append(interface_instance.linear_move(z=self.options.z_axis_start))
if self.options.move_to_origin_end:
footer.append(interface_instance.linear_move(x=0, y=0))
# Generate gcode
gcode_compiler = Compiler(custom_interface, self.options.travel_speed, self.options.cutting_speed,
self.options.pass_depth, dwell_time=self.options.dwell_time, custom_header=header,
custom_footer=footer, unit=self.options.unit)
transformation = Transformation()
transformation.add_translation(self.options.horizontal_offset, self.options.vertical_offset)
transformation.add_scale(self.options.scaling_factor)
if self.options.machine_origin == "center":
transformation.add_translation(-self.options.bed_width / 2, self.options.bed_height / 2)
elif self.options.machine_origin == "top-left":
transformation.add_translation(0, self.options.bed_height)
self.clear_debug()
curves = parse_root(root, transform_origin=not self.options.invert_y_axis, root_transformation=transformation,
canvas_height=self.options.bed_height)
gcode_compiler.append_curves(curves)
gcode_compiler.compile_to_file(output_path, passes=self.options.passes)
# Draw debug lines
if self.options.draw_debug:
self.draw_debug_traces(curves)
self.draw_unit_reference()
self.select_non_debug_layer()
return self.document
def draw_debug_traces(self, curves):
"""Traces arrows over all parsed paths"""
root = self.document.getroot()
origin = self.options.machine_origin
bed_width = self.options.bed_width
bed_height = self.options.bed_height
group = etree.Element("{%s}g" % svg_name_space)
group.set("id", "debug_traces")
group.set("{%s}groupmode" % inkscape_name_space, "layer")
group.set("{%s}label" % inkscape_name_space, "debug traces")
group.append(
etree.fromstring(xml_tree.tostring(debug_methods.arrow_defs(arrow_scale=self.options.debug_arrow_scale))))
for curve in curves:
approximation = LineSegmentChain.line_segment_approximation(curve)
change_origin = Transformation()
if not self.options.invert_y_axis:
change_origin.add_scale(1, -1)
change_origin.add_translation(0, -bed_height)
if origin == "center":
change_origin.add_translation(bed_width / 2, bed_height / 2)
path_string = xml_tree.tostring(
debug_methods.to_svg_path(approximation, color="red", opacity="0.5",
stroke_width=f"{self.options.debug_line_width}px",
transformation=change_origin, draw_arrows=True)
)
group.append(etree.fromstring(path_string))
root.append(group)
def draw_unit_reference(self):
"""Draws reference points to mark the bed's four corners"""
root = self.document.getroot()
unit = self.options.unit
origin = self.options.machine_origin
bed_width = self.options.bed_width
bed_height = self.options.bed_height
group = etree.Element("{%s}g" % svg_name_space)
group.set("id", "debug_references")
group.set("{%s}groupmode" % inkscape_name_space, "layer")
group.set("{%s}label" % inkscape_name_space, "debug reference points")
reference_points_svg = [(0, 0), (0, bed_height), (bed_width, 0), (bed_width, bed_height)]
reference_points_gcode = {
"bottom-left": [(0, bed_height), (0, 0), (bed_width, bed_height), (bed_width, 0)],
"top-left": [(0, 0), (0, bed_height), (bed_width, 0), (bed_width, bed_height)],
"center": [(-bed_width / 2, bed_height / 2), (-bed_width / 2, -bed_height / 2),
(bed_width / 2, bed_height / 2),
(bed_width / 2, -bed_height / 2)]
}[origin]
for i, (x, y) in enumerate(reference_points_svg):
reference_point = etree.Element("{%s}g" % svg_name_space)
stroke_width = 2
size = 7
x_direction = -1 if x > 0 else 1
plus_sign = etree.Element("{%s}g" % svg_name_space)
horizontal = etree.Element("{%s}line" % svg_name_space)
horizontal.set("x1", str(x - x_direction * stroke_width / 2))
horizontal.set("y1", str(y))
horizontal.set("x2", str(x + x_direction * size))
horizontal.set("y2", str(y))
horizontal.set("style", f"stroke:black;stroke-width:{stroke_width}")
plus_sign.append(horizontal)
y_direction = -1 if y > 0 else 1
vertical = etree.Element("{%s}line" % svg_name_space)
vertical.set("x1", str(x))
vertical.set("y1", str(y + stroke_width / 2))
vertical.set("x2", str(x))
vertical.set("y2", str(y + y_direction * size))
vertical.set("style", f"stroke:black;stroke-width:{stroke_width}")
plus_sign.append(vertical)
reference_point.append(plus_sign)
text_box = etree.Element("{%s}text" % svg_name_space)
text_box.set("x", str(x - 28))
text_box.set("y", str(y - (y <= 0) * 6 + (y > 0) * 9))
text_box.set("font-size", "6")
text_box.text = f"{reference_points_gcode[i][0]}{unit}, {reference_points_gcode[i][1]}{unit}"
reference_point.append(text_box)
group.append(reference_point)
root.append(group)
def select_non_debug_layer(self):
"""
Select content_layer and create one if it doesn't exist. This helps stop the user from accidentally placing new
objects in debug layers.
"""
root = self.document.getroot()
unique_id = "layer89324"
content_layer = root.find("{%s}g[@id='%s']" % (svg_name_space, unique_id))
if content_layer is None:
content_layer = etree.Element("{%s}g" % svg_name_space)
content_layer.set("id", unique_id)
content_layer.set("{%s}groupmode" % inkscape_name_space, "layer")
content_layer.set("{%s}label" % inkscape_name_space, "content layer")
sodipodi = root.find("{%s}namedview" % sodipodi_name_space)
if sodipodi is not None:
sodipodi.set("{%s}current-layer" % inkscape_name_space, unique_id)
root.append(content_layer)
def clear_debug(self):
"""Removes debug groups. Used before parsing paths for gcode."""
root = self.document.getroot()
debug_traces = root.find("{%s}g[@id='debug_traces']" % svg_name_space)
debug_references = root.find("{%s}g[@id='debug_references']" % svg_name_space)
if debug_traces is not None:
root.remove(debug_traces)
if debug_references is not None:
root.remove(debug_references)
def add_arguments(self, arg_parser):
"""Tell inkscape what arguments to stick in self.options (behind the hood it's more complicated, see docs)"""
arguments = self.read_arguments()
for arg in arguments:
arg_parser.add_argument("--" + arg["name"], type=arg["type"], dest=arg["name"])
@staticmethod
def read_arguments():
"""
This method reads arguments off of the inx file so you don't have to explicitly declare them in self.add_arguments()
"""
root = etree.parse(inx_filename).getroot()
arguments = [] # [{name, type, ...}]
namespace = "http://www.inkscape.org/namespace/inkscape/extension"
for arg in root.iter("{%s}param" % namespace):
name = arg.attrib["name"]
arg_type = arg.attrib["type"]
if arg_type in ["description", "notebook"]:
continue
types = {"int": int, "float": float, "bool": Boolean, "string": str, "optiongroup": str, "path": str}
arguments.append({"name": name, "type": types[arg_type]})
if next(root.iter("{%s}page" % namespace)) is not None:
arguments.append({"name": "tabs", "type": str})
return arguments
if __name__ == '__main__':
JTechPhotonicsLaserTool().run()

View File

@ -0,0 +1,30 @@
[
{
"name": "J Tech Photonics Laser Tool",
"id": "fablabchemnitz.de.j_tech_photonics_laser_tool",
"path": "j_tech_photonics_laser_tool",
"dependent_extensions": null,
"original_name": "J Tech Community Laser Tool",
"original_id": "community.jtechphotonics.com",
"license": "GNU GPL v2",
"license_url": "https://jtechphotonics.com/Downloads/Inkscape/JTP-Laser-Tool_v1.1-beta_ink1.0.zip",
"comment": "",
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/j_tech_photonics_laser_tool",
"fork_url": "https://github.com/JTechPhotonics/J-Tech-Photonics-Laser-Tool",
"documentation_url": "https://stadtfabrikanten.org/display/IFM/J+Tech+Photonics+Laser+Tool",
"inkscape_gallery_url": null,
"main_authors": [
"github.com/JTechPhotonics",
"github.com/PadLex",
"github.com/odaki",
"github.com/themanyone",
"github.com/drewler",
"github.com/nineff",
"github.com/4cello",
"github.com/dapperfu",
"github.com/nmeurer",
"github.com/aspeteRakete",
"github.com/vmario89"
]
}
]

View File

@ -0,0 +1,378 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
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):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='bendy_straw')
self.add_argument('--pattern_type', type=self.str, default='origami')
self.add_argument('--parameter_type', type=self.str, default='angles')
self.add_argument('--n', type=self.int, default=6)
self.add_argument('--lines', type=self.int, default=3)
self.add_argument('--radius', type=self.float, default=25.0)
# self.add_argument('--attachment_length', type=self.float, default=3.0)
# self.add_argument('--attachment_length', type=self.int, default=20)
self.add_argument('--radial_ratio', type=self.float, default=0.75)
# self.add_argument('--alpha1', type=self.float, default=45.0)
# self.add_argument('--alpha2', type=self.float, default=45.0)
self.add_argument('--alpha1', type=self.int, default=45)
self.add_argument('--alpha2', type=self.int, default=35)
self.add_argument('--h1', type=self.float, default=1)
self.add_argument('--h2', type=self.float, default=2)
self.add_argument('--vertex_base_outer_bool', type=self.bool, default=False)
self.add_argument('--vertex_base_inner_bool', type=self.bool, default=False)
self.add_argument('--vertex_radius_outer_bool', type=self.bool, default=False)
self.add_argument('--vertex_radius_inner_bool', type=self.bool, default=False)
self.add_argument('--add_attachment', type=self.bool, default=False)
# slot options for support ring
self.add_argument('--base_height', type=self.float, default=5.0)
self.add_argument('--add_base_slot', type=self.bool, default=False)
self.add_argument('--center_base_slot', type=self.bool, default=False)
self.add_argument('--base_slot_height', type=self.float, default=3.0)
self.add_argument('--base_slot_width', type=self.float, default=3.0)
self.add_argument('--distance', type=self.float, default=3.0)
self.add_argument('--add_distance_slot', type=self.bool, default=False)
self.add_argument('--distance_slot_height', type=self.float, default=3.0)
self.add_argument('--distance_slot_width', type=self.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
#
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = Bendy_Straw() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,98 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import math
import numpy as np
from math import pi
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
def reflections_diag(path):
new_paths = [path]
new_paths = new_paths + Path.list_reflect(new_paths, (0, 0), (1, 1))
return new_paths + Path.list_reflect(new_paths, (0, 0), (1, -1))
def reflections_rect(path):
new_paths = [path]
new_paths = new_paths + Path.list_reflect(new_paths, (0, 0), (0, 1))
return new_paths + Path.list_reflect(new_paths, (0, 0), (1, 0))
def recenter(paths, dist):
# paths_new = Path.list_simplify(paths)
paths_new = Path.list_rotate(paths, pi/4)
return Path.list_add(paths_new, (dist, dist))
class MasuBox(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='boxes_masu')
self.add_argument('--width', type=self.float, default=10.0)
self.add_argument('--height', type=self.float, default=10.0)
self.add_argument('--width_delta', type=self.float, default=0.0)
self.add_argument('--width_delta_bool', type=self.bool, default=False)
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
width = self.options.width * unit_factor
height = self.options.height * unit_factor
if self.options.width_delta_bool:
width_delta = self.options.width_delta * unit_factor
width += width_delta
height -= width_delta/2
length = math.sqrt(2)*(width + 2*height)
half_fold = 90 if self.options.simulation_mode else 180
# bottom of box
ring_inner = Path.generate_square(width, width, center = [0,0], style = 'm', fold_angle=half_fold)
# ring making the corners
lengths = [height, width, height]
points = Path.get_square_points(sum(lengths), sum(lengths), [0,0])
styles = ['vmv','mmm']
ring_middle = [Path([points[i], points[(i + 1)%4]], 'm').
break_path(lengths, styles[i % 2]) for i in range(4)]
# arms along width and length
points = [(-width / 2, -(width / 2 + 0 * height)),
(-width / 2, -(width / 2 + 1 * height)),
(-width / 2, -(width / 2 + 2 * height)),
(+width / 2, -(width / 2 + 2 * height)),
(+width / 2, -(width / 2 + 1 * height)),
(+width / 2, -(width / 2 + 0 * height))]
arms_ = [Path.list_create_from_points(points, 'mmvmm', fold_angles = [180, 180, half_fold, 180, 180]),
Path.list_create_from_points(points, 'mvvvm', half_fold)]
arms = [Path.list_rotate(arms_[i % 2], i * pi / 2) for i in range(4)]
# tiny corner diagonals
diag = Path([(width/2, width/2), (width/2 + height, width/2 + height)], 'v')
corner_diagonals = [diag * (1, i*pi/2) for i in range(4)]
self.edge_points = Path.get_square_points(length, length)
self.path_tree = [ring_inner, ring_middle, arms, corner_diagonals]
self.path_tree = recenter(self.path_tree, length/2)
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = MasuBox() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,54 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from math import pi
import inkex
import math
from Path import Path
from Boxes_Masu import MasuBox
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
def reflections_diag(path):
new_paths = [path]
new_paths = new_paths + Path.list_reflect(new_paths, (0, 0), (1, 1))
return new_paths + Path.list_reflect(new_paths, (0, 0), (1, -1))
def reflections_rect(path):
new_paths = [path]
new_paths = new_paths + Path.list_reflect(new_paths, (0, 0), (0, 1))
return new_paths + Path.list_reflect(new_paths, (0, 0), (1, 0))
class MasuBoxSquare(MasuBox):
def __init__(self):
""" Constructor
"""
MasuBox.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--length', type=self.float, default=10.0)
def generate_path_tree(self):
""" Specialized path generation for your origami pattern
"""
# retrieve saved parameters, and apply unit factor where needed
self.options.width = self.options.length / (2 * math.sqrt(2))
self.options.height = self.options.width/2
self.options.width_delta = 0.0
self.options.width_delta_bool = False
MasuBox.generate_path_tree(self)
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = MasuBoxSquare() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,321 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from abc import abstractmethod
from math import pi, sin, cos, tan, asin, acos, atan, sqrt
from itertools import accumulate
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
def generate_slot_line(n, slot_position,
slot_height, slot_width,
base_height, base_width):
if slot_height == 0 and slot_width == 0:
return []
slot_height = min(slot_height, base_height)
slot_width = min(slot_width, base_width)
rect = [ (0, 0),
(0, slot_height),
(slot_width, slot_height),
(slot_width, 0)]
dx = (base_width - slot_width) / 2
if slot_position == -1:
dy = 0
elif slot_position == 0:
dy = (base_height - slot_height) / 2
elif slot_position == +1:
dy = base_height - slot_height
slot = Path(rect, 'c', closed=True) + (dx, dy)
slots = [slot + (base_width * i, 0) for i in range(n)]
divider = Path([(base_width, 0), (base_width, base_height)], style='m')
dividers = [divider + (base_width*i, 0) for i in range(n-1)]
return slots + dividers
class Cylindrical(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--radius', type=self.float, default=10.0)
self.add_argument('--sides', type=self.int, default=6)
self.add_argument('--rows', type=self.int, default=3)
self.add_argument('--extra_column', type=self.bool, default=False)
# slot options for support ring
self.add_argument('--add_base_slot', type=self.bool, default=False)
self.add_argument('--base_slot_position', type=self.str, default="1")
self.add_argument('--base_height', type=self.float, default=5.0)
self.add_argument('--base_slot_height', type=self.float, default=3.0)
self.add_argument('--base_slot_width', type=self.float, default=3.0)
self.add_argument('--add_middle_slot', type=self.bool, default=False)
self.add_argument('--middle_slot_position', type=self.str, default="0")
self.add_argument('--distance', type=self.float, default=3.0)
self.add_argument('--middle_slot_height', type=self.float, default=3.0)
self.add_argument('--middle_slot_width', type=self.float, default=3.0)
@abstractmethod
def parse_parameters(self):
"""
"""
pass
@abstractmethod
def generate_cell(self):
""" Generate the the origami cell
"""
pass
def generate_path_tree(self):
""" Specialized path generation for your origami pattern
"""
# zero distances when slot option not selected
if not self.options.add_base_slot:
self.options.base_height = 0
self.options.base_slot_height = 0
if not self.options.add_middle_slot:
self.options.distance = 0
self.options.middle_slot_height = 0
if self.options.base_height == 0:
self.options.add_base_slot = False
if self.options.distance == 0:
self.options.add_middle_slot = False
self.parse_parameters()
# pre-calculate width before adding one to sides, for easier attachment
self.options.width = 2 * self.options.radius * sin(pi / self.options.sides)
self.options.cols = self.options.sides + self.options.extra_column
# get cell definitions
cell_data = self.generate_cell()
# calculate divider if it doesn't exist
if 'divider' not in cell_data:
points = Path.get_points(cell_data['interior'])
x = [p[0] for p in points if p[1] == 0]
cell_data['divider'] = Path([(min(x), 0),
(max(x), 0)], style='m')
points = Path.get_points(cell_data['divider'])
x = [p[0] for p in points]
DX = max(x) - min(x)
# DX = 0
# if 'edge_right' not in cell_data and 'edge_left' not in cell_data:
# cell_data['edge_left'] = []
# for interior in cell_data['interior']:
# points = Path.get_points(interior)
# x = [p[0] for p in points]
# y = [p[1] for p in points]
# top = [p for p in points if p[1] == min(y)]
# top_x = [p[0] for p in top]
# # top_y = [p[1] for p in top]
# bot = [p for p in points if p[1] == max(y)]
# bot_x = [p[0] for p in bot]
# # bot_y = [p[1] for p in bot]
# top_left = [p for p in top if p[0] == min(top_x)][0]
# bot_left = [p for p in bot if p[0] == min(bot_x)][0]
# cell_data['edge_left'].append(Path([top_left, bot_left], 'e'))
if 'edge_right' not in cell_data and 'edge_left' in cell_data:
cell_data['edge_right'] = []
for edge_left in cell_data['edge_left']:
edge_right = edge_left + (DX, 0)
edge_right.invert()
cell_data['edge_right'].append(edge_right)
if 'edge_right' in cell_data and 'edge_left' not in cell_data:
cell_data['edge_left'] = []
for edge_right in cell_data['edge_right']:
edge_left = edge_right + (-DX, 0)
edge_left.invert()
cell_data['edge_left'].append(edge_left)
cell_data['dx'], cell_data['dy'] = self.get_dxdy(cell_data)
# get all slots and vertical dividers between slots
base, middle = self.generate_all_slots(cell_data)
slots = [[base['slots'], middle['slots']]]
# get horizontal dividers between cells
dividers = self.generate_horizontal_dividers(cell_data)
# finish by replicating the actual interior
interior = self.generate_interior(cell_data)
# use slots and cell data to create the full edge paths
self.edge_points = self.generate_fused_edge_points(base, middle, cell_data)
self.path_tree = [dividers, interior]
if len(self.vertex_points) == 0:
self.vertex_points = Path.get_points(self.path_tree)
self.path_tree.append(slots)
def get_dxdy(self, cell_data):
dx = [0]
dy = [0]
for edge in cell_data['edge_left']:
dx.append(edge.points[1][0] - edge.points[0][0])
dy.append(edge.points[1][1] - edge.points[0][1])
return list(accumulate(dx)), list(accumulate(dy))
def generate_interior(self, cell_data):
# retrieve conversion factor for selected unit
unit_factor = self.calc_unit_factor()
rows = self.options.rows
base_height = self.options.base_height * unit_factor
distance = self.options.distance * unit_factor
interiors = []
for i in range(rows):
dx = cell_data['dx'][i]
dy = cell_data['dy'][i] + base_height + i * distance
pattern = cell_data['interior'][i]
interiors.append(Path.list_add(pattern, (dx, dy)))
return interiors
def generate_horizontal_dividers(self, cell_data):
# retrieve conversion factor for selected unit
unit_factor = self.calc_unit_factor()
rows = self.options.rows
base_height = self.options.base_height * unit_factor
distance = self.options.distance * unit_factor
divider = cell_data['divider']
dividers = []
if self.options.add_base_slot:
dividers.append(divider + (0, base_height))
for i in range(1, rows):
dx = cell_data['dx'][i]
dy = cell_data['dy'][i] + base_height + (i - 1) * distance
dividers.append(divider + (dx, dy))
if self.options.add_middle_slot:
dividers.append(divider + (dx, dy + distance))
if self.options.add_base_slot:
dx = cell_data['dx'][-1]
dy = cell_data['dy'][-1] + base_height + (rows - 1) * distance
dividers.append(divider + (dx, dy))
return dividers
# pass
def generate_all_slots(self, cell_data):
dx_ = cell_data['dx']
dy_ = cell_data['dy']
# retrieve conversion factor for selected unit
unit_factor = self.calc_unit_factor()
# retrieve saved parameters, and apply unit factor where needed
cols = self.options.cols
rows = self.options.rows
width = self.options.width * unit_factor
dist = self.options.distance * unit_factor
base_height = self.options.base_height * unit_factor
height = [dy_[i] + base_height + (i - 1) * dist for i in range(rows+1)]
base = {'left': [],
'right': [],
'slots': []}
if self.options.add_base_slot:
base_slot_height = self.options.base_slot_height * unit_factor
base_slot_width = self.options.base_slot_width * unit_factor
base_slot_sizes = [base_slot_height, base_slot_width, base_height, width]
base_slot_top = generate_slot_line(cols, +int(self.options.base_slot_position), *base_slot_sizes)
base_slot_bot = generate_slot_line(cols, -int(self.options.base_slot_position), *base_slot_sizes)
base['slots'] = [base_slot_top, Path.list_add(base_slot_bot, (dx_[-1], height[-1]))]
base['left'] = [Path([(0, 0), (0, base_height)], style = 'e'),
Path([(dx_[-1], height[-1]),
(dx_[-1], height[-1] + base_height)], style = 'e')]
base['right'] = [Path([(dx_[-1] + cols*width, height[-1] + base_height),
(dx_[-1] + cols*width, height[-1] + base_height)], style = 'e'),
Path([(cols*width, base_height),
(cols*width, 0)], style = 'e')]
middle = {'left': [],
'right': [],
'slots': []}
if self.options.add_middle_slot:
middle_slot_height = self.options.middle_slot_height * unit_factor
middle_slot_width = self.options.middle_slot_width * unit_factor
middle_slot_sizes = [middle_slot_height, middle_slot_width, dist, width]
middle_slot = generate_slot_line(cols, +int(self.options.middle_slot_position), *middle_slot_sizes)
middle['slots'] = [Path.list_add(middle_slot,
(dx_[i], height[i]))
for i in range(1, rows)]
middle['left'] = [Path([(0, 0),
(0, dist)], style='e') +
(dx_[i+1], dy_[1] + dist + height[i]) for i in range(rows-1)]
middle['right'] = [
Path([(0, height[rows-2] + base_height + (rows - 1) * dist),
(0, dy_[-2] + base_height + (rows - 2) * dist)], style='e') +
(dx_[-(i+2)] + cols*width, -dy_[i] - i*dist) for i in range(rows - 1)]
return base, middle
def generate_fused_edge_points(self, base, middle, cell_data):
unit_factor = self.calc_unit_factor()
base_height = self.options.base_height * unit_factor
distance = self.options.distance * unit_factor
rows = self.options.rows
edges = []
if self.options.add_base_slot: edges.append(base['left'][0])
for i in range(rows):
cell_left = cell_data['edge_left'][i]
dx = cell_data['dx'][i]
edges.append(cell_left + (dx, cell_data['dy'][i] + base_height + i * distance))
if self.options.add_middle_slot and i < rows - 1:
edges.append(middle['left'][i] + (0, 0))
if self.options.add_base_slot: edges.append(base['left'][1])
if self.options.add_base_slot: edges.append(base['right'][0])
for i in range(rows):
cell_right = cell_data['edge_right'][-(i + 1)]
dx = cell_data['dx'][-(i + 2)]
edges.append(cell_right + (dx, cell_data['dy'][rows - i - 1] + base_height + (rows - i - 1) * distance))
if self.options.add_middle_slot and i < rows - 1:
edges.append(middle['right'][i] + (0, 0))
if self.options.add_base_slot: edges.append(base['right'][1])
return Path.get_points(edges)

View File

@ -0,0 +1,377 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
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):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='bendy_straw')
self.add_argument('--pattern_type', type=self.str, default='origami')
self.add_argument('--parameter_type', type=self.str, default='angles')
self.add_argument('--n', type=self.int, default=6)
self.add_argument('--lines', type=self.int, default=3)
self.add_argument('--radius', type=self.float, default=25.0)
# self.add_argument('--attachment_length', type=self.float, default=3.0)
# self.add_argument('--attachment_length', type=self.int, default=20)
self.add_argument('--radial_ratio', type=self.float, default=0.75)
# self.add_argument('--alpha1', type=self.float, default=45.0)
# self.add_argument('--alpha2', type=self.float, default=45.0)
self.add_argument('--alpha1', type=self.int, default=45)
self.add_argument('--alpha2', type=self.int, default=35)
self.add_argument('--h1', type=self.float, default=1)
self.add_argument('--h2', type=self.float, default=2)
self.add_argument('--vertex_base_outer_bool', type=self.bool, default=False)
self.add_argument('--vertex_base_inner_bool', type=self.bool, default=False)
self.add_argument('--vertex_radius_outer_bool', type=self.bool, default=False)
self.add_argument('--vertex_radius_inner_bool', type=self.bool, default=False)
self.add_argument('--add_attachment', type=self.bool, default=False)
# slot options for support ring
self.add_argument('--base_height', type=self.float, default=5.0)
self.add_argument('--add_base_slot', type=self.bool, default=False)
self.add_argument('--center_base_slot', type=self.bool, default=False)
self.add_argument('--base_slot_height', type=self.float, default=3.0)
self.add_argument('--base_slot_width', type=self.float, default=3.0)
self.add_argument('--distance', type=self.float, default=3.0)
self.add_argument('--add_distance_slot', type=self.bool, default=False)
self.add_argument('--distance_slot_height', type=self.float, default=3.0)
self.add_argument('--distance_slot_width', type=self.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
#
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = Bendy_Straw() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,163 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from math import pi, sin, asin, cos, tan, acos, sqrt
import inkex
import os
from Path import Path
from Pattern import Pattern
from Cylindrical import Cylindrical
class Kresling(Cylindrical):
def __init__(self):
""" Constructor
"""
Cylindrical.__init__(self) # Must be called in order to parse common options
self.add_argument('--pattern', type=self.str, default="kresling")
self.add_argument('--measure_value', type=self.float, default=10.0)
self.add_argument('--measure_type', type=self.str, default=60)
self.add_argument('--parameter_type', type=self.str, default=60)
self.add_argument('--radial_ratio', type=self.float, default=0.5)
self.add_argument('--angle_ratio', type=self.float, default=0.5)
self.add_argument('--lambdatheta', type=self.float, default=45)
def parse_parameters(self):
n = self.options.sides
theta = pi * (n - 2) / (2 * n)
# define ratio parameter
parameter = self.options.parameter_type
if parameter == 'radial_ratio':
radial_ratio = self.options.radial_ratio
max_radial_ratio = sin((pi / 4) * (1. - 2. / n))
if radial_ratio > max_radial_ratio:
inkex.errormsg(
_("For polygon of {} sides, the maximal radial ratio is = {}".format(n, max_radial_ratio)))
radial_ratio = max_radial_ratio
self.options.angle_ratio = 1 - 2 * n * asin(radial_ratio) / ((n - 2) * pi)
elif parameter == 'lambdatheta':
lambdatheta = self.options.lambdatheta
angle_min = 45. * (1 - 2. / n)
angle_max = 2 * angle_min
if lambdatheta < angle_min:
inkex.errormsg(_(
"For polygon of {} sides, phi must be between {} and {} degrees, \nsetting lambda*theta = {}\n".format(
n, angle_min, angle_max, angle_min)))
lambdatheta = angle_min
elif lambdatheta > angle_max:
inkex.errormsg(_(
"For polygon of {} sides, phi must be between {} and {} degrees, \nsetting lambda*theta = {}\n".format(
n, angle_min, angle_max, angle_max)))
lambdatheta = angle_max
self.options.angle_ratio = lambdatheta * n / (90. * (n - 2.))
# define some length
mtype = self.options.measure_type
mvalue = self.options.measure_value
angle_ratio = self.options.angle_ratio
if mtype == 'a':
radius = 0.5 * mvalue / (sin(pi / n))
if mtype == 'b':
A = cos(theta * (1 - angle_ratio))
B = sin(pi / n)
C = cos(theta * angle_ratio)
radius = 0.5 * mvalue / sqrt(A ** 2 + B ** 2 - 2 * A * B * C)
elif mtype == 'l':
radius = 0.5 * mvalue / cos(theta * (1 - angle_ratio))
elif mtype == 'radius_external':
radius = mvalue
elif mtype == 'radius_internal':
radius = mvalue / (sin(theta * (1 - angle_ratio)))
elif mtype == 'diameter_external':
radius = 0.5 * mvalue
elif mtype == 'diameter_internal':
radius = 0.5 * mvalue / sin(theta * (1 - angle_ratio))
if self.options.pattern == 'mirrowed':
self.options.mirror_cells = True
else:
self.options.mirror_cells = False
self.options.radius = radius
def generate_cell(self):
""" Generate the the origami cell
"""
# retrieve conversion factor for selected unit
unit_factor = self.calc_unit_factor()
rows = self.options.rows
sides = self.options.sides
cols = self.options.cols
radius = self.options.radius * unit_factor
width = self.options.width * unit_factor
# vertex_radius = self.options.vertex_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))
dy = l * sin(theta * angle_ratio)
dx = l * cos(theta * angle_ratio) - width
# init dict that holds everything
cell_data = {}
# divider (supposed to be the same)
cell_data['divider'] = Path([(0, 0), (width * cols, 0)], style='m')
# IMPORTANT: left edges from TOP to BOTTOM
edge_left = [Path([(0, 0), (dx, dy)], style='e')]
if mirror_cells:
edge_left.append(Path([(0, 0), (-dx, dy)], style='e'))
cell_data['edge_left'] = [edge_left[i % (1 + mirror_cells)] for i in range(rows)]
# IMPORTANT: right edges from BOTTOM to TOP
edge_right = [Path([(cols * width + dx, dy), (cols * width, 0)], style='e')]
if mirror_cells:
edge_right.append(Path([(cols * width - dx, dy), (cols * width, 0)], style='e'))
cell_data['edge_right'] = [edge_right[i % (1 + mirror_cells)] for i in range(rows)]
# rest of cell
zigzags = [Kresling.generate_kresling_zigzag(sides, cols, radius, angle_ratio)]
if mirror_cells:
zigzags.append(Path.list_reflect(zigzags[0], (0, dy / 2), (dx, dy / 2)))
zigzags[1] = Path.list_add(zigzags[1], (-dx, 0))
cell_data['interior'] = [zigzags[i % (1 + mirror_cells)] for i in range(rows)]
return cell_data
@staticmethod
def generate_kresling_zigzag(sides, cols, radius, angle_ratio):
# 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)
dy = l * sin(theta * angle_ratio)
dx = l * cos(theta * angle_ratio) - a
points = []
styles = []
for i in range(cols):
points.append((i * a, 0))
points.append(((i + 1) * a + dx, dy))
styles.append('v')
if i != cols - 1:
styles.append('m')
# elif add_attachment:
# points.append((sides * a, 0))
# styles.append('m')
path = Path.generate_separated_paths(points, styles)
return path
if __name__ == '__main__':
e = Kresling()
e.draw()

View File

@ -0,0 +1,73 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from abc import abstractmethod
from math import pi, sin, cos, tan, asin, acos, atan, sqrt
import inkex
from Path import Path
from Pattern import Pattern
from Cylindrical import Cylindrical
# 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
class Template(Cylindrical):
def __init__(self):
""" Constructor
"""
Cylindrical.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='cylindrical_template')
self.add_argument('--length', type=self.float, default=10.)
self.add_argument('--angle', type=self.int, default=0)
def generate_cell(self):
""" Generate the the origami cell
"""
# retrieve conversion factor for selected unit
unit_factor = self.calc_unit_factor()
sides = self.options.sides
cols = self.options.cols
rows = self.options.rows
length = self.options.length * unit_factor
angle = self.options.angle * unit_factor
width = self.options.width * unit_factor # use pre-calculated width
dx = length * sin(pi * angle / 180)
dy = length * cos(pi * angle / 180)
# init dict that holds everything
cell_data = {}
# divider can be set for performance, or it can be calculated automatically, supposing a mountain fold
# cell_data['divider'] = Path([(0,0), (width*cols, 0)], style='m')
# Only left or right edges can be implemented, or both for performance
# IMPORTANT: left edges from TOP to BOTTOM
cell_data['edge_left'] = [Path([(0,0), (dx, dy)], style='e')]*rows
# # IMPORTANT: right edges from BOTTOM to TOP
# cell_data['edge_right'] = [Path([(cols*width + dx, dy), (cols*width, 0)], style='e')]*rows
# rest of cell
single = [Path([(0, 0), (width + dx, dy)], 'v'), Path([(width + dx, dy), (width, 0)], 'm')]
pattern = [Path.list_add(single, (width*i, 0)) for i in range(cols)]
pattern = Path.list_simplify(pattern)
cell_data['interior'] = [pattern]*rows
return cell_data
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = Template() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,122 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from math import pi, tan, sqrt, sin, cos
import inkex
from Path import Path
from Pattern import Pattern
class Hypar(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='template1')
self.add_argument('--radius', type=self.float, default=10.0)
self.add_argument('--sides', type=self.int, default=4)
self.add_argument('--rings', type=self.int, default=7)
self.add_argument('--simplify_center', type=self.bool, default=0)
def generate_path_tree(self):
""" Specialized path generation for your origami pattern
"""
# retrieve saved parameters
unit_factor = self.calc_unit_factor()
vertex_radius = self.options.vertex_radius * unit_factor
pattern = self.options.pattern
radius = self.options.radius * unit_factor
sides = self.options.sides
rings = self.options.rings
simplify_center = self.options.simplify_center
sin_ = sin(pi / float(sides))
a = radius*sin_ # half of length of polygon side
H = radius*sqrt(1 - sin_**2)
polygon = Path.generate_polygon(sides, radius, 'e')
# # OLD diagonals generation with universal creases
# diagonals = []
# for i in range(sides):
# diagonals.append(Path([(0, 0), polygon.points[i]], 'u'))
# points = [(x, y) for x, y in polygon.points]
# diagonals = diagonals + [Path.generate_separated_paths(points, 'm')]
# # modify center if needed
# if simplify_center:
# for i in range(sides):
# if i % 2 == 0:
# p2 = diagonals[i].points[1]
# diagonals[i].points[0] = (1. / (rings + 1) * p2[0], 1. / (rings + 1) * p2[1])
# separate generic closed ring to create edges
self.edge_points = polygon.points
# vertex and diagonal lines creation
vertex_line = []
diagonal_line = []
for i in range(1, rings + 2):
y1 = a * (float(i - 1) / (rings + 1.))
x1 = H * float(i - 1) / (rings + 1.)
y2 = a * (float(i) / (rings + 1.))
x2 = H * float(i) / (rings + 1.)
vertex_line.append((Path((x2, y2), style='p', radius=vertex_radius)))
diagonal_line.append((Path([(x1, y1), (x2, y2)], style='m' if i % 2 else 'v')))
# rotation of vertices and diagonals for completing the drawing
diagonals = []
vertices = [Path((0, 0), style='p', radius=vertex_radius)]
for i in range(sides):
vertices = vertices+Path.list_rotate(vertex_line, i * 2 * pi / float(sides))
diagonals = diagonals+[Path.list_rotate(diagonal_line, i * 2 * pi / float(sides))]
# modify center if needed
if simplify_center:
for i in range(sides):
if i % 2 == 0:
del diagonals[i][0]
# inkex.debug(len(diagonals))
# inkex.debug(len(diagonals[0]))
# diagonals = diagonals + diagonal
# scale generic closed ring to create inner rings
inner_rings = []
for i in range(rings + 1):
inner_rings.append(polygon * (float(i)/(rings+1)))
inner_rings[i].style = 'v' if i % 2 else 'm'
# create points for zig zag pattern
zig_zags = []
if pattern != "classic":
zig_zag = []
for i in range(1, rings + 1):
y_out = a * ((i + 1.) / (rings + 1.))
y_in = a * (float(i) / (rings + 1.))
x_out = H * (i + 1.) / (rings + 1.)
x_in = H * float(i) / (rings + 1.)
if pattern == "alternate_asymmetric" and i % 2:
zig_zag.append(Path([(x_in, -y_in), (x_out, +y_out)], style='u'))
else:
zig_zag.append(Path([(x_in, +y_in), (x_out, -y_out)], style='u'))
# reflect zig zag pattern to create all sides
zig_zags.append(zig_zag)
for i in range(sides - 1):
points = diagonals[i][0].points
zig_zags.append(Path.list_reflect(zig_zags[i], points[0], points[1]))
self.translate = (radius, radius)
self.path_tree = [diagonals, zig_zags, inner_rings, vertices]
# Main function, creates an instance of the Class and calls inkex.affect() to draw the origami on inkscape
if __name__ == '__main__':
e = Hypar() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,162 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from math import pi, sin, cos, tan, acos, sqrt
import inkex
import os
from Path import Path
from Pattern import Pattern
class Kresling(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
self.add_argument('--pattern', type=self.str, default="kresling")
self.add_argument('--lines', type=self.int, default=1)
self.add_argument('--sides', type=self.int, default=3)
self.add_argument('--add_attachment', type=self.bool, default=False)
self.add_argument('--attachment_percentage', type=self.float, default=100.)
self.add_argument('--mirror_cells', type=self.bool, default=False)
@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__':
e = Kresling()
e.draw()

View File

@ -0,0 +1,92 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from math import sin, cos, sqrt, asin, pi, ceil
import inkex
from Path import Path
from Pattern import Pattern
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=self.float, default=10.0)
self.add_argument('--measure_type', type=self.str, default=60)
self.add_argument('--parameter_type', type=self.str, default=60)
self.add_argument('--radial_ratio', type=self.float, default=0.5)
self.add_argument('--angle_ratio', type=self.float, default=0.5)
self.add_argument('--lambdatheta', type=self.float, default=45)
def generate_path_tree(self):
""" Convert radial to angular ratio, then call regular Kresling constructor
"""
n = self.options.sides
theta = pi*(n-2)/(2*n)
# define ratio parameter
parameter = self.options.parameter_type
if parameter == 'radial_ratio':
radial_ratio = self.options.radial_ratio
max_radial_ratio = sin((pi/4)*(1. - 2./n))
if radial_ratio > max_radial_ratio:
inkex.errormsg(_("For polygon of {} sides, the maximal radial ratio is = {}".format(n, max_radial_ratio)))
radial_ratio = max_radial_ratio
self.options.angle_ratio = 1 - 2*n*asin(radial_ratio)/((n-2)*pi)
elif parameter == 'lambdatheta':
lambdatheta = self.options.lambdatheta
angle_min = 45. * (1 - 2. / n)
angle_max = 2 * angle_min
if lambdatheta < angle_min:
inkex.errormsg(_(
"For polygon of {} sides, phi must be between {} and {} degrees, \nsetting lambda*theta = {}\n".format(
n, angle_min, angle_max, angle_min)))
lambdatheta = angle_min
elif lambdatheta > angle_max:
inkex.errormsg(_(
"For polygon of {} sides, phi must be between {} and {} degrees, \nsetting lambda*theta = {}\n".format(
n, angle_min, angle_max, angle_max)))
lambdatheta = angle_max
self.options.angle_ratio = lambdatheta * n / (90. * (n - 2.))
# define some length
mtype = self.options.measure_type
mvalue = self.options.measure_value
angle_ratio = self.options.angle_ratio
if mtype == 'a':
radius = 0.5*mvalue / (sin(pi/n))
if mtype == 'b':
A = cos(theta*(1-angle_ratio))
B = sin(pi/n)
C = cos(theta*angle_ratio)
radius = 0.5*mvalue / sqrt(A**2 + B**2 - 2*A*B*C)
elif mtype == 'l':
radius = 0.5*mvalue/cos(theta*(1-angle_ratio))
elif mtype == 'radius_external':
radius = mvalue
elif mtype == 'radius_internal':
radius = mvalue/(sin(theta*(1-angle_ratio)))
elif mtype == 'diameter_external':
radius = 0.5*mvalue
elif mtype == 'diameter_internal':
radius = 0.5*mvalue/sin(theta*(1-angle_ratio))
# inkex.errormsg(_("Value = {}, Mode = {}, Radius = {}".format(mvalue, mtype, radius)))
if self.options.pattern == 'mirrowed':
self.options.mirror_cells = True
else:
self.options.mirror_cells = False
self.options.radius = radius
Kresling.generate_path_tree(self)
if __name__ == '__main__':
e = Kresling_Full()
e.draw()

View File

@ -0,0 +1,787 @@
"""
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, sqrt
# 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
Attributes
---------
points: tuple or list of tuples
Points defining stroke lines.
style: str
Single character defining style of stroke. Default values are:
'm' for mountain creases
'v' for valley creases
'e' for edge borders
Extra possible values:
'u' for universal creases
's' for semicreases
'c' for kirigami cuts
angle: float
From 0 to 180 degrees, converted to an opacity level from 0 to 1. This is how OrigamiSimulator encodes maximum
fold angles
closed: bool
Tells if desired path should contain a last stroke from the last point to the first point, closing the path
radius: float
If only one point is given, it's assumed to be a circle and radius sets the radius
Methods
---------
invert(self)
Inverts path
Overloaded Operators
---------
__add__(self, offsets)
Adding a tuple to a Path returns a new path with all points having an offset defined by the tuple
__mul__(self, transform)
Define multiplication of a Path to a vector in complex exponential representation
Static Methods
---------
draw_paths_recursively(path_tree, group, styles_dict)
Draws strokes defined on "path_tree" to "group". Styles dict maps style of path_tree element to the definition
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.
generate_vgrid(cls, xlims, ylims, nb_of_divisions, style, include_edge=False)
Generate list of Path instances, in which each Path is a stroke defining a vertical grid dividing the space
xlims * ylims nb_of_divisions times.
generate_separated_paths(cls, points, styles, closed=False)
Generate list of Path instances, in which each Path is the stroke between each two point tuples, in case each
stroke must be handled separately
reflect(cls, path, p1, p2)
Reflects each point of path on line defined by two points and return new Path instance with new reflected points
list_reflect(cls, paths, p1, p2)
Generate list of new Path instances, rotation each path by transform
list_rotate(cls, paths, theta, translation=(0, 0))
Generate list of new Path instances, rotation each path by transform
list_add(cls, paths, offsets)
Generate list of new Path instances, adding a different tuple for each list
list_mul(cls, paths, transf)
Generate list of new Path instances, multiplying 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, fold_angle = 180.0):
""" Constructor
Parameters
---------
points: list of 2D tuples
stroke will connect all points
style: str
Single character defining style of stroke. For use with the OrigamiPatterns class (probably the only
project that will ever use this file) the default values are:
'm' for mountain creases
'v' for valley creases
'e' for edge borders
closed: bool
if true, last point will be connected to first point at the end
invert: bool
if true, stroke will start at the last point and go all the way to the first one
"""
if type(points) == list and len(points) != 1:
self.type = 'linear'
if invert:
self.points = points[::-1]
else:
self.points = points
elif (type(points) == list and len(points) == 1):
self.type = 'circular'
self.points = points
self.radius = radius
elif (type(points) == tuple and len(points) == 2):
self.type = 'circular'
self.points = [points]
self.radius = radius
else:
raise TypeError("Points must be tuple of length 2 (for a circle) or a list of tuples of length 2 each")
self.fold_angle = max(min(fold_angle, 180.), 0.)
self.style = style
self.closed = closed
def invert(self):
""" Inverts path
"""
self.points = self.points[::-1]
"""
Draw path recursively
- Static method
- Draws strokes defined on "path_tree" to "group"
- Inputs:
-- path_tree [nested list] of Path instances
-- group [inkex.etree.SubElement]
-- styles_dict [dict] containing all styles for path_tree
"""
@staticmethod
def draw_paths_recursively(path_tree, group, styles_dict):
""" Static method, draw list of Path instances recursively
"""
for subpath in path_tree:
if type(subpath) == list:
if len(subpath) == 1:
subgroup = group
else:
subgroup = inkex.etree.SubElement(group, 'g')
Path.draw_paths_recursively(subpath, subgroup, styles_dict)
else:
# ~ if subpath.style != 'n':
if subpath.style != 'n' and styles_dict[subpath.style]['draw']:
if subpath.type == 'linear':
points = subpath.points
path = 'M{},{} '.format(*points[0])
for i in range(1, len(points)):
path = path + 'L{},{} '.format(*points[i])
if subpath.closed:
path = path + 'L{},{} Z'.format(*points[0])
attribs = {'style': format_style(styles_dict[subpath.style]),
'd': path,
'opacity': str(subpath.fold_angle/180)}
inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), attribs)
else:
attribs = {'style': format_style(styles_dict[subpath.style]),
'cx': str(subpath.points[0][0]), 'cy': str(subpath.points[0][1]),
'r': str(subpath.radius),
'opacity': str(subpath.fold_angle/180)}
inkex.etree.SubElement(group, inkex.addNS('circle', 'svg'), attribs)
@classmethod
def get_average_point(cls, paths):
points = cls.get_points(paths)
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return (x/n, y/n)
@classmethod
def get_square_points(cls, width, height, center = None, rotation = 1):
""" Get points of a square at given center or origin
Parameters
---------
width: float
height: float
center: list of floats
rotation: float
rotation in degrees
Returns
---------
points: list of tuples
"""
if center is None:
center = [width/2, height/2]
#TODO: Implement rotation
# c = cos(rotation * pi / 180)
# s = sin(rotation * pi / 180)
points = [
(center[0] - 0.5*width, center[1] + 0.5*height), # top left
(center[0] + 0.5*width, center[1] + 0.5*height), # top right
(center[0] + 0.5*width, center[1] - 0.5*height), # bottom right
(center[0] - 0.5*width, center[1] - 0.5*height)] # bottom left
# points = [
# (center[0] + (-0.5*width*c - 0.5*height*s), center[1] + (-0.5*width*s + 0.5*height*c)), # top left
# (center[0] + (+0.5*width*c - 0.5*height*s), center[1] + (+0.5*width*s + 0.5*height*c)), # top right
# (center[0] + (+0.5*width*c + 0.5*height*s), center[1] - (+0.5*width*s - 0.5*height*c)), # bottom right
# (center[0] + (-0.5*width*c + 0.5*height*s), center[1] - (-0.5*width*s - 0.5*height*c))] # bottom left
return points
@classmethod
def generate_square(cls, width, height, style ='e', fold_angle=180, center = None, rotation = 0):
""" Generate a closed square at given center or origin
Parameters
---------
width: float
height: float
style: str
fold_angle: float
center: list of floats
rotation: float
rotation in degrees
Returns
---------
path: path instance
"""
points = cls.get_square_points(width, height, center, rotation)
return Path(points, style, fold_angle=fold_angle, closed=True)
@classmethod
def generate_hgrid(cls, xlims, ylims, nb_of_divisions, style, include_edge=False, fold_angle = 180):
""" 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.
All lines are alternated, to minimize Laser Cutter unnecessary movements
Parameters
---------
xlims: tuple
Defines x_min and x_max for space that must be divided.
ylims: tuple
Defines y_min and y_max for space that must be divided.
nb_of_divisions: int
Defines how many times it should be divided.
style: str
Single character defining style of stroke.
include_edge: bool
Defines if edge should be drawn or not.
fold_angle: float
Returns
---------
paths: list of Path instances
"""
rect_len = (ylims[1] - ylims[0])/nb_of_divisions
hgrid = []
for i in range(1 - include_edge, nb_of_divisions + include_edge):
hgrid.append(cls([(xlims[0], ylims[0]+i*rect_len),
(xlims[1], ylims[0]+i*rect_len)],
style=style, invert=i % 2 == 0, fold_angle = fold_angle))
return hgrid
@classmethod
def generate_vgrid(cls, xlims, ylims, nb_of_divisions, style, include_edge=False, fold_angle = 180):
""" Generate list of Path instances, in which each Path is a stroke defining
a vertical grid dividing the space xlims * ylims nb_of_divisions times.
All lines are alternated, to minimize Laser Cutter unnecessary movements
Parameters
---------
-> refer to generate_hgrid
Returns
---------
paths: list of Path instances
"""
rect_len = (xlims[1] - xlims[0])/nb_of_divisions
vgrid = []
for i in range(1 - include_edge, nb_of_divisions + include_edge):
vgrid.append(cls([(xlims[0]+i*rect_len, ylims[0]),
(xlims[0]+i*rect_len, ylims[1])],
style=style, invert=i % 2 == 0, fold_angle = fold_angle))
return vgrid
@classmethod
def generate_polygon(cls, sides, radius, style, center=(0, 0), fold_angle = 180):
points = []
for i in range(sides):
points.append((radius * cos((1 + i * 2) * pi / sides),
radius * sin((1 + i * 2) * pi / sides)))
return Path(points, style, closed=True, fold_angle = fold_angle)
@classmethod
def generate_separated_paths(cls, points, styles, closed=False, fold_angle = 180):
""" Generate list of Path instances, in which each Path is the stroke
between each two point tuples, in case each stroke must be handled separately.
Returns
---------
paths: list
list of Path instances
"""
paths = []
if type(styles) == str:
styles = [styles] * (len(points) - 1 + int(closed))
elif len(styles) != len(points) - 1 + int(closed):
raise TypeError("Number of paths and styles don't match")
for i in range(len(points) - 1 + int(closed)):
j = (i+1)%len(points)
paths.append(cls([points[i], points[j]],
styles[i], fold_angle = fold_angle))
return paths
def __add__(self, offsets):
""" " + " operator overload.
Adding a tuple to a Path returns a new path with all points having an offset
defined by the tuple
"""
if type(offsets) == list:
if len(offsets) != 1 or len(offsets) != len(self.points):
raise TypeError("Paths can only be added by a tuple of a list of N tuples, "
"where N is the same number of points")
elif type(offsets) != tuple:
raise TypeError("Paths can only be added by tuples")
else:
offsets = [offsets] * len(self.points)
# if type(self.points) == list:
points_new = []
for point, offset in zip(self.points, offsets):
points_new.append((point[0]+offset[0],
point[1]+offset[1]))
if self.type == 'circular':
radius = self.radius
else:
radius = 0.2
# if self.type == 'circular' else 0.1
return Path(points_new, self.style, self.closed, radius=radius, fold_angle=self.fold_angle)
@classmethod
def list_add(cls, paths, offsets):
""" Generate list of new Path instances, adding a different tuple for each list
Parameters
---------
paths: Path or list
list of N Path instances
offsets: tuple or list
list of N tuples
Returns
---------
paths_new: list
list of N Path instances
"""
if type(paths) == Path and type(offsets) == tuple:
paths = [paths]
offsets = [offsets]
elif type(paths) == list and type(offsets) == tuple:
offsets = [offsets] * len(paths)
elif type(paths) == Path and type(offsets) == list:
paths = [paths] * len(offsets)
elif type(paths) == list and type(offsets) == list:
if len(paths) == 1:
paths = [paths[0]] * len(offsets)
elif len(offsets) == 1:
offsets = [offsets[0]] * len(paths)
elif len(offsets) != len(paths):
raise TypeError("List of paths and list of tuples must have same length. {} paths and {} offsets "
" where given".format(len(paths), len(offsets)))
else:
pass
paths_new = []
for path, offset in zip(paths, offsets):
if type(path) == Path:
paths_new.append(path+offset)
elif type(path) == list:
paths_new.append(
cls.list_add(path, offset)
)
return paths_new
@classmethod
def list_mul(cls, paths, offsets):
""" Generate list of new Path instances, multiplying a different tuple for each list
Parameters
---------
paths: Path or list
list of N Path instances
offsets: tuple or list
list of N tuples
Returns
---------
paths_new: list
list of N Path instances
"""
if type(paths) == Path and type(offsets) == tuple:
paths = [paths]
offsets = [offsets]
elif type(paths) == list and type(offsets) == tuple:
offsets = [offsets] * len(paths)
elif type(paths) == Path and type(offsets) == list:
paths = [paths] * len(offsets)
elif type(paths) == list and type(offsets) == list:
if len(paths) == 1:
paths = [paths[0]] * len(offsets)
elif len(offsets) == 1:
offsets = [offsets[0]] * len(paths)
elif len(offsets) != len(paths):
raise TypeError("List of paths and list of tuples must have same length. {} paths and {} offsets "
" where given".format(len(paths), len(offsets)))
else:
pass
paths_new = []
for path, offset in zip(paths, offsets):
paths_new.append(path*offset)
return paths_new
def break_path(self, lengths, styles = None):
if len(self.points) != 2:
raise ValueError('Path breaking only implemented for straight lines with 2 points')
if styles is None:
styles = [self.style]*len(lengths)
elif len(styles) != len(lengths):
raise ValueError('Different number of lenghts and styles')
p0 = self.points[0]
p1 = self.points[1]
d = (p1[0]-p0[0], p1[1]-p0[1])
L = sqrt(d[0]**2 + d[1]**2)
dx = d[0] / L
dy = d[1] / L
paths = []
start = 0
p0_ = p0
for l, s in zip(lengths, styles):
p1_ = (p0_[0] + dx*l, p0_[1] + dy*l)
paths.append(Path([p0_, p1_], style = s))
p0_ = p1_
return paths
def __mul__(self, transform):
""" " * " operator overload.
Define multiplication of a Path to a vector in complex exponential representation
Parameters
---------
transform: float of tuple of length 2 or 4
if float, transform represents magnitude
Example: path * 3
if tuple length 2, transform[0] represents magnitude and transform[1] represents angle of rotation
Example: path * (3, pi)
if tuple length 4, transform[2],transform[3] define a different axis of rotation
Example: path * (3, pi, 1, 1)
"""
points_new = []
# "temporary" (probably permanent) compatibility hack
try:
long_ = long
except:
long_ = int
if isinstance(transform, (int, long_, float)):
for p in self.points:
points_new.append((transform * p[0],
transform * p[1]))
elif isinstance(transform, (list, tuple)):
if len(transform) == 2:
u = transform[0]*cos(transform[1])
v = transform[0]*sin(transform[1])
x_, y_ = 0, 0
elif len(transform) == 4:
u = transform[0]*cos(transform[1])
v = transform[0]*sin(transform[1])
x_, y_ = transform[2:]
else:
raise IndexError('Paths can only be multiplied by a number or a tuple/list of length 2 or 4')
for p in self.points:
x, y = p[0]-x_, p[1]-y_
points_new.append((x_ + x * u - y * v,
y_ + x * v + y * u))
else:
raise TypeError('Paths can only be multiplied by a number or a tuple/list of length 2 or 4')
if self.type == 'circular':
radius = self.radius
else:
radius = 0.2
return Path(points_new, self.style, self.closed, radius=radius, fold_angle=self.fold_angle)
def shape(self):
points = self.points
x = [p[0] for p in points]
y = [p[1] for p in points]
return [min(x), max(x), min(y), max(y)]
@classmethod
def list_create_from_points(cls, points, styles, fold_angles = None):
""" Generate list of new Path instances, between each two points
Parameters
---------
points: list of tuples
list of points
styles: str or list of str
styles
fold_angles: list of floats
list of maximum fold angle values
Returns
---------
paths_new: list
list of N Path instances
"""
if fold_angles is None:
fold_angles = [180]
elif type(fold_angles) != list:
fold_angles = [fold_angles]
return [Path([points[i], points[i+1]],
styles[i % len(styles)],
fold_angle=fold_angles[i % len(fold_angles)]) for i in range(len(points)-1)]
@classmethod
def list_rotate_symmetry(cls, paths, n, translation=(0,0)):
""" Generate list of new Path instances, rotation each path by transform
Parameters
---------
paths: Path or list
list of N Path instances
n: int
number of rotations
translation: tuple or list 2
axis of rotation
Returns
---------
paths_new: list
list of N Path instances
"""
theta = 2*pi/n
paths_new = []
for i in range(n):
ith_rotation = cls.list_rotate(paths, theta, translation=translation)
if type(paths) == list:
paths_new += ith_rotation
else:
paths_new.append(ith_rotation)
return paths_new
@classmethod
def list_rotate(cls, paths, theta, translation=(0, 0)):
""" Generate list of new Path instances, rotation each path by transform
Parameters
---------
paths: Path or list
list of N Path instances
theta: float (radians)
angle of rotation
translation: tuple or list 2
axis of rotation
Returns
---------
paths_new: list
list of N Path instances
"""
if len(translation) != 2:
TypeError("Translation must have length 2")
if type(paths) != list:
paths = [paths]
paths_new = []
for path in paths:
if type(path) == Path:
paths_new.append(path*(1, theta, translation[0], translation[1]))
elif type(path) == list:
paths_new.append(cls.list_rotate(path, theta, translation))
if len(paths_new) == 1:
paths_new = paths_new[0]
return paths_new
# TODO:
# Apparently it's not working properly, must be debugged and tested
@classmethod
def reflect(cls, path, p1, p2):
""" Reflects each point of path on line defined by two points and return new Path instance with new reflected points
Parameters
---------
path: Path
p1: tuple or list of size 2
p2: tuple or list of size 2
Returns
---------
path_reflected: Path
"""
(x1, y1) = p1
(x2, y2) = p2
if x1 == x2 and y1 == y2:
ValueError("Duplicate points don't define a line")
elif x1 == x2:
t_x = [-1, 0, 2*x1, 1]
t_y = [0, 1, 0, 1]
else:
m = (y2 - y1)/(x2 - x1)
t = y1 - m*x1
t_x = [1 - m**2, 2*m, -2*m*t, m**2 + 1]
t_y = [2*m, m**2 - 1, +2*t, m**2 + 1]
points_new = []
for p in path.points:
x_ = (t_x[0]*p[0] + t_x[1]*p[1] + t_x[2]) / t_x[3]
y_ = (t_y[0]*p[0] + t_y[1]*p[1] + t_y[2]) / t_y[3]
points_new.append((x_, y_))
return Path(points_new, path.style, path.closed, fold_angle=path.fold_angle)
# TODO:
# Apparently it's not working properly, must be debugged and tested
@classmethod
def list_reflect(cls, paths, p1, p2):
""" Generate list of new Path instances, rotation each path by transform
Parameters
---------
paths: Path or list
list of N Path instances
p1: tuple or list of size 2
p2: tuple or list of size 2
Returns
---------
paths_new: list
list of N Path instances
"""
if type(paths) == Path:
paths = [paths]
paths_new = []
for path in paths:
paths_new.append(Path.reflect(path, p1, p2))
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)
@classmethod
def get_points(cls, paths):
""" Get points of path tree in drawing order.
"""
points = []
if type(paths) == Path:
points = points + paths.points
elif type(paths) == list:
for sub_path in paths:
points = points + Path.get_points(sub_path)
return points

View File

@ -0,0 +1,378 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""
Helper functions
"""
import os
from abc import abstractmethod
from Path import Path, inkex, simplestyle
class Pattern(inkex.Effect):
""" Class that inherits inkex.Effect and further specializes it for different
Patterns generation
Attributes
---------
styles_dict: dict
defines styles for every possible stroke. Default values are:
styles_dict = {'m' : mountain_style,
'v' : valley_style,
'e' : edge_style}
topgroup: inkex.etree.SubElement
Top Inkscape group element
path_tree: nested list
Contains "tree" of Path instances, defining new groups for each
sublist
translate: 2 sized tuple
Defines translation to be added when drawing to Inkscape (default: 0,0)
Methods
---------
effect(self)
Main function, called when the extension is run.
create_styles_dict(self)
Get stroke style parameters and use them to create the styles dictionary.
calc_unit_factor(self)
Return the scale factor for all dimension conversions
add_text(self, node, text, position, text_height=12)
Create and insert a single line of text into the svg under node.
get_color_string(self, longColor, verbose=False)
Convert the long into a #RRGGBB color value
Abstract Methods
---------
__init__(self)
Parse all options
generate_path_tree(self)
Generate nested list of Path
"""
@abstractmethod
def generate_path_tree(self):
""" Generate nested list of Path instances
Abstract method, must be defined in all child classes
"""
pass
@abstractmethod
def __init__(self):
""" Parse all common options
Must be reimplemented in child classes to parse specialized options
"""
inkex.Effect.__init__(self) # initialize the super class
# backwards compatibility
try:
self.add_argument = self.arg_parser.add_argument
self.str = str
self.int = int
self.float = float
self.bool = inkex.Boolean
except:
self.add_argument = self.OptionParser.add_option
self.str = "string"
self.int = "int"
self.float = "float"
self.bool = "inkbool"
# Two ways to get debug info:
# OR just use inkex.debug(string) instead...
try:
self.tty = open("/dev/tty", 'w')
except:
self.tty = open(os.devnull, 'w') # '/dev/null' for POSIX, 'nul' for Windows.
self.add_argument('-u', '--units', type=self.str, default='mm')
# bypass most style options for OrigamiSimulator
self.add_argument('--simulation_mode', type=self.bool, default=False)
# mountain options
self.add_argument('--mountain_stroke_color', type=self.str, default=4278190335) # Red
self.add_argument('--mountain_stroke_width', type=self.float, default=0.1)
self.add_argument('--mountain_dashes_len', type=self.float, default=1.0)
self.add_argument('--mountain_dashes_duty', type=self.float, default=0.5)
self.add_argument('--mountain_dashes_bool', type=self.bool, default=True)
self.add_argument('--mountain_bool', type=self.bool, default=True)
self.add_argument('--mountain_bool_only', type=self.bool, default=False)
# valley options
self.add_argument('--valley_stroke_color', type=self.str, default=65535) # Blue
self.add_argument('--valley_stroke_width', type=self.float, default=0.1)
self.add_argument('--valley_dashes_len', type=self.float, default=1.0)
self.add_argument('--valley_dashes_duty', type=self.float, default=0.25)
self.add_argument('--valley_dashes_bool', type=self.bool, default=True)
self.add_argument('--valley_bool', type=self.bool, default=True)
self.add_argument('--valley_bool_only', type=self.bool, default=False)
# edge options
self.add_argument('--edge_stroke_color', type=self.str, default=255) # Black
self.add_argument('--edge_stroke_width', type=self.float, default=0.1)
self.add_argument('--edge_dashes_len', type=self.float, default=1.0)
self.add_argument('--edge_dashes_duty', type=self.float, default=0.25)
self.add_argument('--edge_dashes_bool', type=self.bool, default=False)
self.add_argument('--edge_bool', type=self.bool, default=True)
self.add_argument('--edge_bool_only', type=self.bool, default=False)
self.add_argument('--edge_single_path', type=self.bool, default=True)
# universal crease options
self.add_argument('--universal_stroke_color', type=self.str, default=4278255615) # Magenta
self.add_argument('--universal_stroke_width', type=self.float, default=0.1)
self.add_argument('--universal_dashes_len', type=self.float, default=1.0)
self.add_argument('--universal_dashes_duty', type=self.float, default=0.25)
self.add_argument('--universal_dashes_bool', type=self.bool, default=False)
self.add_argument('--universal_bool', type=self.bool, default=True)
self.add_argument('--universal_bool_only', type=self.bool, default=False)
# semicrease options
self.add_argument('--semicrease_stroke_color', type=self.str, default=4294902015) # Yellow
self.add_argument('--semicrease_stroke_width', type=self.float, default=0.1)
self.add_argument('--semicrease_dashes_len', type=self.float, default=1.0)
self.add_argument('--semicrease_dashes_duty', type=self.float, default=0.25)
self.add_argument('--semicrease_dashes_bool', type=self.bool, default=False)
self.add_argument('--semicrease_bool', type=self.bool, default=True)
self.add_argument('--semicrease_bool_only', type=self.bool, default=False)
# cut options
self.add_argument('--cut_stroke_color', type=self.str, default=16711935) # Green
self.add_argument('--cut_stroke_width', type=self.float, default=0.1)
self.add_argument('--cut_dashes_len', type=self.float, default=1.0)
self.add_argument('--cut_dashes_duty', type=self.float, default=0.25)
self.add_argument('--cut_dashes_bool', type=self.bool, default=False)
self.add_argument('--cut_bool', type=self.bool, default=True)
self.add_argument('--cut_bool_only', type=self.bool, default=False)
# vertex options
self.add_argument('--vertex_stroke_color', type=self.str, default=255) # Black
self.add_argument('--vertex_stroke_width', type=self.float, default=0.1)
self.add_argument('--vertex_radius', type=self.float, default=0.1)
self.add_argument('--vertex_dashes_bool', type=self.bool, default=False)
self.add_argument('--vertex_bool', type=self.bool, default=True)
self.add_argument('--vertex_bool_only', type=self.bool, default=False)
# here so we can have tabs - but we do not use it directly - else error
self.add_argument('--active-tab', type=self.str, default='title') # use a legitimate default
self.path_tree = []
self.edge_points = []
self.vertex_points = []
self.translate = (0, 0)
def effect(self):
""" Main function, called when the extension is run.
"""
# bypass most style options if simulation mode is choosen
self.check_simulation_mode()
# 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()
# get paths for selected origami pattern
self.generate_path_tree()
# ~ accuracy = self.options.accuracy
# ~ unit_factor = self.calc_unit_factor()
# 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]),
# inkex.addNS('transform-center-y','inkscape'): str(-bbox_center[1]),
inkex.addNS('transform-center-x', 'inkscape'): str(0),
inkex.addNS('transform-center-y', 'inkscape'): str(0),
'transform': 'translate(%s,%s)' % self.translate}
# add the group to the document's current layer
if type(self.path_tree) == list and len(self.path_tree) != 1:
self.topgroup = inkex.etree.SubElement(self.get_layer(), 'g', g_attribs)
else:
self.topgroup = self.get_layer()
if len(self.edge_points) == 0:
Path.draw_paths_recursively(self.path_tree, self.topgroup, self.styles_dict)
elif self.options.edge_single_path:
edges = Path(self.edge_points, 'e', closed=True)
Path.draw_paths_recursively(self.path_tree + [edges], self.topgroup, self.styles_dict)
else:
edges = Path.generate_separated_paths(self.edge_points, 'e', closed=True)
Path.draw_paths_recursively(self.path_tree + edges, self.topgroup, self.styles_dict)
# self.draw_paths_recursively(self.path_tree, self.topgroup, self.styles_dict)
# compatibility hack, "affect()" is replaced by "run()"
def draw(self):
try:
self.run() # new
except:
self.affect() # old
# close(self.tty)
self.tty.close()
# compatibility hack
def get_layer(self):
try:
return self.svg.get_current_layer() # new
except:
return self.current_layer # old
def check_simulation_mode(self):
if not self.options.simulation_mode:
pass
else:
self.options.mountain_stroke_color = 4278190335
self.options.mountain_dashes_len = 0
self.options.mountain_dashes_bool = False
self.options.mountain_bool_only = False
self.options.mountain_bool = True
self.options.valley_stroke_color = 65535
self.options.valley_dashes_len = 0
self.options.valley_dashes_bool = False
self.options.valley_bool_only = False
self.options.valley_bool = True
self.options.edge_stroke_color = 255
self.options.edge_dashes_len = 0
self.options.edge_dashes_bool = False
self.options.edge_bool_only = False
self.options.edge_bool = True
self.options.universal_stroke_color = 4278255615
self.options.universal_dashes_len = 0
self.options.universal_dashes_bool = False
self.options.universal_bool_only = False
self.options.universal_bool = True
self.options.cut_stroke_color = 16711935
self.options.cut_dashes_len = 0
self.options.cut_dashes_bool = False
self.options.cut_bool_only = False
self.options.cut_bool = True
self.options.vertex_bool = False
def create_styles_dict(self):
""" Get stroke style parameters and use them to create the styles dictionary, used for the Path generation
"""
unit_factor = self.calc_unit_factor()
def create_style(type):
style = {'draw': getattr(self.options,type+"_bool"),
'stroke': self.get_color_string(getattr(self.options,type+"_stroke_color")),
'fill': 'none',
'stroke-width': getattr(self.options,type+"_stroke_width") * unit_factor}
if getattr(self.options,type+"_dashes_bool"):
dash_gap_len = getattr(self.options,type+"_dashes_len")
duty = getattr(self.options,type+"_dashes_duty")
dash = (dash_gap_len * unit_factor) * duty
gap = (dash_gap_len * unit_factor) * (1 - duty)
style['stroke-dasharray'] = "{} {}".format(dash, gap)
return style
self.styles_dict = {'m': create_style("mountain"),
'v': create_style("valley"),
'u': create_style("universal"),
's': create_style("semicrease"),
'c': create_style("cut"),
'e': create_style("edge"),
'p': create_style("vertex")}
def get_color_string(self, longColor, verbose=False):
""" Convert the long into a #RRGGBB color value
- verbose=true pops up value for us in defaults
conversion back is A + B*256^1 + G*256^2 + R*256^3
"""
# compatibility hack, no "long" in Python 3
try:
longColor = long(longColor)
if longColor < 0: longColor = long(longColor) & 0xFFFFFFFF
hexColor = hex(longColor)[2:-3]
except:
longColor = int(longColor)
hexColor = hex(longColor)[2:-2]
inkex.debug = inkex.utils.debug
hexColor = '#' + hexColor.rjust(6, '0').upper()
if verbose: inkex.debug("longColor = {}, hex = {}".format(longColor,hexColor))
return hexColor
def add_text(self, node, text, position, text_height=12):
""" Create and insert a single line of text into the svg under node.
"""
line_style = {'font-size': '%dpx' % text_height, 'font-style':'normal', 'font-weight': 'normal',
'fill': '#F6921E', 'font-family': 'Bitstream Vera Sans,sans-serif',
'text-anchor': 'middle', 'text-align': 'center'}
line_attribs = {inkex.addNS('label','inkscape'): 'Annotation',
'style': simplestyle.formatStyle(line_style),
'x': str(position[0]),
'y': str((position[1] + text_height) * 1.2)
}
line = inkex.etree.SubElement(node, inkex.addNS('text','svg'), line_attribs)
line.text = text
def calc_unit_factor(self):
""" Return the scale factor for all dimension conversions.
- The document units are always irrelevant as
everything in inkscape is expected to be in 90dpi pixel units
"""
# namedView = self.document.getroot().find(inkex.addNS('namedview', 'sodipodi'))
# doc_units = self.getUnittouu(str(1.0) + namedView.get(inkex.addNS('document-units', 'inkscape')))
# backwards compatibility
try:
return self.svg.unittouu(str(1.0) + self.options.units)
except:
try:
return inkex.unittouu(str(1.0) + self.options.units)
except AttributeError:
return self.unittouu(str(1.0) + self.options.units)

View File

@ -0,0 +1,101 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from math import pi, sin, cos
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
class PleatCircular(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='pleat_circular')
self.add_argument('--radius', type=self.float, default=55.0)
self.add_argument('--ratio', type=self.float, default=0.4)
self.add_argument('--rings', type=self.int, default=15)
self.add_argument('--sides', type=self.int, default=20)
def generate_path_tree(self):
""" Specialized path generation for your origami pattern
"""
# retrieve saved parameters
unit_factor = self.calc_unit_factor()
R = self.options.radius * unit_factor
ratio = self.options.ratio
r = R * ratio
rings = self.options.rings
dr = (1.-ratio)*R/rings
self.translate = (R, R)
if not self.options.simulation_mode:
inner_circles = []
for i in range(1, rings):
inner_circles.append(Path((0, 0), radius=r + i*dr, style='m' if i % 2 else 'v'))
edges = [Path((0, 0), radius=R, style='e'),
Path((0, 0), radius=r, style='e')]
self.path_tree = [inner_circles, edges]
# append semicreases for simulation
else:
sides = self.options.sides
dtheta = pi / sides
# create diagonals
diagonals = []
for i in range(sides):
p1 = (0, 0)
p2 = (R * cos((1 + i * 2) * dtheta), R * sin((1 + i * 2) * dtheta))
diagonals.append(Path([p1, p2], 'u'))
s = sin(dtheta)
c = cos(dtheta)
# Edge
paths = [Path([(c * R, -s * R), (R, 0), (c * R, s * R)], style='e'),
Path([(c * r, -s * r), (r, 0), (c * r, s * r)], style='e')]
# MV circles
for i in range(1, rings):
r_i = r + i * dr
paths.append(Path([(c * r_i, -s * r_i), (r_i, 0), (c * r_i, s * r_i)],
style='m' if i % 2 else 'v'))
# Semicreases
top = []
bottom = []
for i in range(rings + 1):
r_i = r + i*dr
top.append((r_i*(1 + (i % 2)*(c-1)), -(i % 2)*s*r_i))
bottom.append((r_i*(1 + (i % 2)*(c-1)), (i % 2)*s*r_i))
paths = paths + [Path([(r, 0), (R, 0)], 's'), # straight line 1
Path([(r*c, r*s), (R*c, R*s)], 's', invert=True), # straight line 2
Path(top, 's'), # top half of semicrease pattern
Path(bottom, 's')] # bottom half of semicrease pattern
all_paths = [paths]
for i in range(1, sides):
all_paths.append(Path.list_rotate(all_paths[0], i*2*dtheta))
self.path_tree = all_paths
# Main function, creates an instance of the Class and calls inkex.affect() to draw the origami on inkscape
if __name__ == '__main__':
e = PleatCircular() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,129 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from math import pi, sin, cos
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
class SupportRing(Pattern):
def __init__(self):
""" Constructor
"""
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=self.int, default=3)
self.add_argument('--radius_external', type=self.float, default=10.0)
self.add_argument('--inverted', type=self.bool, default=False)
self.add_argument('--single_stroke', type=self.bool, default=True)
self.add_argument('--radius_ratio', type=self.float, default=0.5)
self.add_argument('--radius_type', type=self.str, default='polygonal')
self.add_argument('--radius_draw', type=self.bool, default=True)
self.add_argument('--connector_length', type=self.float, default=3.0)
self.add_argument('--connector_thickness', type=self.float, default=3.0)
self.add_argument('--head_length', type=self.float, default=1.0)
self.add_argument('--head_thickness', type=self.float, default=1.0)
self.add_argument('--pattern', type=self.str, 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
inverted = self.options.inverted
sign = -1 if inverted else 1
single_stroke = self.options.single_stroke
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 if inverted else radius_external * radius_ratio
# dradius = abs(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 if inverted else length_external * radius_ratio
external_points = [(-length_external/2, 0),
(-connector_thickness / 2, 0),
(-connector_thickness / 2, -connector_length*sign),
(-connector_thickness / 2 - head_thickness / 2, -connector_length*sign),
(-connector_thickness / 2, -(connector_length + head_length)*sign),
(0, -(connector_length + head_length)*sign),
(+connector_thickness / 2, -(connector_length + head_length)*sign),
(+connector_thickness / 2 + head_thickness / 2, -connector_length*sign),
(+connector_thickness / 2, -connector_length*sign),
(+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))
if single_stroke:
external_lines = Path(Path.get_points(external_lines), 'm')
self.path_tree = [external_lines]
if self.options.radius_draw == True:
# center point of main strokes
outer_average = Path.get_average_point(external_lines)
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))
# move to center
inner_average = Path.get_average_point(internal_lines)
delta = ((outer_average[0] - inner_average[0]),
(outer_average[1] - inner_average[1]))
if single_stroke:
internal_lines = Path(Path.get_points(internal_lines), 'm')
internal_lines = Path.list_add(internal_lines, delta)
elif radius_type == 'circular':
internal_lines = Path(outer_average, radius=radius_internal, style='m')
self.path_tree.append(internal_lines)
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = SupportRing() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,113 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from math import pi
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
class Template(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
# save all custom parameters defined on .inx file
self.add_argument('--pattern', type=self.str, default='template1')
self.add_argument('--length', type=self.float, default=10.0)
self.add_argument('--angle', type=self.int, default=0)
self.add_argument('--fold_angle_valley', type=self.int, default=180)
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
length = self.options.length * unit_factor
vertex_radius = self.options.vertex_radius * unit_factor
pattern = self.options.pattern
angle = self.options.angle * pi / 180
fold_angle_valley = self.options.fold_angle_valley
# create all Path instances defining strokes
# first define its points as a list of tuples...
left_right_stroke_points = [(length / 2, 0),
(length / 2, length)]
up_down_stroke_points = [(0, length / 2),
(length, length / 2)]
# doing the same for diagonals
diagonal_1_stroke_points = [(0, 0),
(length, length)]
diagonal_2_stroke_points = [(0, length),
(length, 0)]
# ... and then create the Path instances, defining its type ('m' for mountain, etc...)
if pattern == 'template1':
up_down = [Path(left_right_stroke_points, 'm', fold_angle = 180.),
Path(up_down_stroke_points, 'm', fold_angle = 180.)]
diagonals = [Path(diagonal_1_stroke_points, 'v', fold_angle = fold_angle_valley),
Path(diagonal_2_stroke_points, 'v', fold_angle = fold_angle_valley)]
else:
up_down = [Path(left_right_stroke_points, 'v', fold_angle = fold_angle_valley),
Path(up_down_stroke_points, 'v', fold_angle = fold_angle_valley)]
diagonals = [Path(diagonal_1_stroke_points, 'm', fold_angle = 180.),
Path(diagonal_2_stroke_points, 'm', fold_angle = 180. )]
vertices = []
for i in range(3):
for j in range(3):
vertices.append(Path(((i/2.) * length, (j/2.) * length), style='p', radius=vertex_radius))
# multiplication is implemented as a rotation, and list_rotate implements rotation for list of Path instances
vertices = Path.list_rotate(vertices, angle, (1 * length, 1 * length))
up_down = Path.list_rotate(up_down, angle, (1 * length, 1 * length))
diagonals = Path.list_rotate(diagonals, angle, (1 * length, 1 * length))
# if Path constructor is called with more than two points, a single stroke connecting all of then will be
# created. Using method generate_separated_paths, you can instead return a list of separated strokes
# linking each two points
# create a list for edge strokes
# create path from points to be able to use the already built rotate method
edges = Path.generate_square(length, length, 'e', rotation = angle)
edges = Path.list_rotate(edges, angle, (1 * length, 1 * length))
# IMPORTANT: the attribute "path_tree" must be created at the end, saving all strokes
self.path_tree = [up_down, diagonals, vertices]
# IMPORTANT: at the end, save edge points as "self.edge_points", to simplify selection of single or multiple
# strokes for the edge
self.edge_points = edges.points
# if you decide not to declare "self.edge_points", then the edge must be explicitly created in the path_tree:
# self.path_tree = [mountains, valleys, vertices, edges]
# FINAL REMARKS:
# division is implemented as a reflection, and list_reflect implements it for a list of Path instances
# here's a commented example:
# line_reflect = (0 * length, 2 * length, 1 * length, 1 * length)
# mountains = Path.list_reflect(mountains, line_reflect)
# valleys = Path.list_reflect(valleys, line_reflect)
# edges = Path.list_reflect(edges, line_reflect)
# Main function, creates an instance of the Class and calls self.draw() to draw the origami on inkscape
# self.draw() is either a call to inkex.affect() or to svg.run(), depending on python version
if __name__ == '__main__':
e = Template() # remember to put the name of your Class here!
e.draw()

View File

@ -0,0 +1,112 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import math
import numpy as np
import inkex
from Path import Path
from Pattern import Pattern
# TODO:
# Add fractional column number option
class Waterbomb(Pattern):
def __init__(self):
""" Constructor
"""
Pattern.__init__(self) # Must be called in order to parse common options
self.add_argument('--pattern', type=self.str, default='waterbomb')
self.add_argument('--pattern_first_line', type=self.str, default='waterbomb')
self.add_argument('--pattern_last_line', type=self.str, default='waterbomb')
self.add_argument('--lines', type=self.int, default=8)
self.add_argument('--columns', type=self.int, default=16)
self.add_argument('--length', type=self.float, default=10.0)
self.add_argument('--phase_shift', type=self.bool, default=True)
def generate_path_tree(self):
""" Specialized path generation for Waterbomb tesselation pattern
"""
unit_factor = self.calc_unit_factor()
length = self.options.length * unit_factor
vertex_radius = self.options.vertex_radius * unit_factor
cols = self.options.columns
lines = self.options.lines
phase_shift = self.options.phase_shift
pattern_first_line = self.options.pattern_first_line
pattern_last_line = self.options.pattern_last_line
# create vertices
vertex_line_types = [[Path(((i / 2.) * length, 0), style='p', radius=vertex_radius) for i in range(2*cols + 1)],
[Path((i * length, 0), style='p', radius=vertex_radius) for i in range(cols + 1)],
[Path(((i + 0.5) * length, 0), style='p', radius=vertex_radius) for i in range(cols)]]
vertices = []
for i in range(2*lines + 1):
if i % 2 == 0 or (pattern_first_line == 'magic_ball' and i == 1) or (pattern_last_line == 'magic_ball' and i == 2*lines - 1):
type = 0
elif(int(i/2 + phase_shift)) % 2 == 0:
type = 1
else:
type = 2
vertices = vertices + Path.list_add(vertex_line_types[type], (0, 0.5*i*length))
# create a list for the horizontal creases and another for the vertical creases
# alternate strokes to minimize laser cutter path
corr_fist_line = length/2 if pattern_first_line == 'magic_ball' else 0
corr_last_line = length/2 if pattern_last_line == 'magic_ball' else 0
grid = [Path.generate_hgrid([0, length*cols], [0, length*lines], lines, 'm'),
Path.generate_vgrid([0, length*cols], [corr_fist_line, length*lines-corr_last_line], 2*cols, 'm')]
vgrid_a = Path.generate_vgrid([0, length * cols], [0, length / 2], 2 * cols, 'v')
vgrid_b = Path.list_add(vgrid_a, (0, (lines - 0.5) * length))
if pattern_first_line == 'magic_ball' and pattern_last_line == 'magic_ball':
grid[1] = [[vgrid_a[i], grid[1][i], vgrid_b[i]] if i % 2 == 0 else
[vgrid_b[i], grid[1][i], vgrid_a[i]] for i in range(len(grid[1]))]
elif pattern_first_line == 'magic_ball':
grid[1] = [[vgrid_a[i], grid[1][i]] if i % 2 == 0 else
[grid[1][i], vgrid_a[i]] for i in range(len(grid[1]))]
elif pattern_last_line == 'magic_ball':
grid[1] = [[grid[1][i], vgrid_b[i]] if i % 2 == 0 else
[vgrid_b[i], grid[1][i]] for i in range(len(grid[1]))]
# create generic valley Path lines, one pointing up and other pointing down
valley_types = [Path([(i * length / 2, (1 - i % 2) * length / 2) for i in range(2 * cols + 1)], 'v'),
Path([( i*length/2, (i % 2)*length/2) for i in range(2 * cols + 1)], 'v')]
# define which lines must be of which type, according to parity and options
senses = np.array([bool((i % 2+i)/2 % 2) for i in range(2*lines)])
senses = 1*senses # converts bool array to 0's and 1's
if phase_shift:
senses = np.invert(senses)
if pattern_first_line == "magic_ball":
senses[0] = ~senses[0]
if pattern_last_line == "magic_ball":
senses[-1] = ~senses[-1]
valleys = [valley_types[senses[i]] + (0, i * length / 2) for i in range(2*lines)]
# convert first and last lines to mountains if magic_ball
if pattern_first_line == "magic_ball":
valleys[0].style = 'm'
if pattern_last_line == "magic_ball":
valleys[-1].style = 'm'
# invert every two lines to minimize laser cutter movements
for i in range(1, 2*lines, 2):
valleys[i].invert()
self.edge_points = [(0*length*cols, 0*length*lines), # top left
(1*length*cols, 0*length*lines), # top right
(1*length*cols, 1*length*lines), # bottom right
(0*length*cols, 1*length*lines)] # bottom left
self.path_tree = [grid, valleys, vertices]
if __name__ == '__main__':
e = Waterbomb()
e.draw()

View File

@ -0,0 +1,31 @@
module draw_cone(R,n,h,thickness){
difference(){
cylinder(h=h, r1=R+thickness, r2=R+thickness, center=true, $fn=n);
cylinder(h=h, r1=R, r2=R, center=true, $fn=n);
cylinder(h=h, r1=R, r2=R, center=true, $fn=n);
}
}
module draw_cut_boxes(R, n, thickness, slot_height, slot_width){
union(){
for (i=[0: n/2]){
rotate(a=i*360/n, v=[0,0,1])
cube([2*(R+thickness),slot_height,slot_width], center=true);
}
}
}
module draw_belt(R, n, h, thickness, slot_height, slot_width){
difference(){
rotate(a=180/n, v=[0,0,1]) draw_cone(R, n, h, thickness);
draw_cut_boxes(R, n, thickness, slot_height, slot_width);
}
}

View File

@ -0,0 +1,13 @@
include <Belt.scad>
// Input parameters
R = 35;
n = 8;
height = 7; // height of support
thickness = 1; // thickness of belt
// square cuts to be pierced by support ring
slot_height=3; // must be smaller than height
slot_width=3;
draw_belt(R, n, height, thickness, slot_height, slot_width);

View File

@ -0,0 +1,5 @@
# Origami_Patterns_Support_Belt
Designed to be used with the [Origami Patterns Inkscape extension](https://github.com/evbernardes/Origami_Patterns).
3D Print this with TPU (or any other flexible material) and use together with the support rings.

View File

@ -0,0 +1,384 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 128 128"
inkscape:export-ydpi="45"
inkscape:export-xdpi="45"
inkscape:export-filename="/home/valessio/Desenvolvimento/inkscape/inkscape/inkscape.png"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
sodipodi:docname="logo.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
sodipodi:version="0.32"
id="svg2"
height="128"
width="128"
version="1.0"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<title
id="title7387">Inkscape Logo</title>
<sodipodi:namedview
bordercohor="#666666"
inkscape:window-height="716"
inkscape:window-width="1366"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
inkscape:zoom="2.5937425"
inkscape:cx="60.144752"
inkscape:cy="65.349587"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-maximized="1"
inkscape:document-units="px"
inkscape:pagecheckerboard="0"
inkscape:snap-intersection-paths="true" />
<defs
id="defs4" />
<style
type="text/css"
id="style26">
.specularity {opacity:0.5;}
.low-specularity {opacity:0.25;}
.full-specularity {opacity:1;}
.black {fill:#000000;}
.white {fill:#ffffff;}
.outline-big {stroke-width:16;stroke:none;opacity:0.1;fill:none;}
.outline-small {stroke-width:8;stroke:none;opacity:0.2;fill:none;}
.stroke-highlight {fill:none;stroke:none;opacity:0.2;}
.base-shadow {fill:black;opacity:75;}
</style>
<!-- Copyright License -->
<metadata
id="metadata49">
<rdf:RDF>
<cc:Work
rdf:about="etiquette-icon">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Andy Fitzsimon</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>Andrew Michael Fitzsimon</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>Fitzsimon IT Consulting Pty Ltd</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>http://andy.fitzsimon.com.au</dc:identifier>
<dc:date>2006</dc:date>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
<dc:title>Inkscape Logo</dc:title>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Inkscape Flat Logo 2 Color Variant">
<g
id="g11223-6"
transform="translate(-363.14098,-180.14807)">
<path
id="path6262-1"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 433.13709,195.71708 -1.30659,1.30659 -7.75944,-7.75944" />
<path
id="path6256-5"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 410.05994,203.59956 2.87293,2.87293 9.44881,-9.44882 9.44882,9.44882 4.28302,-4.28302" />
<path
id="path6250-9"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 442.06249,215.13814 -0.78317,0.78317 -9.44882,-9.44882 -9.44882,9.44882 -9.44881,-9.44882 -9.44882,9.44882 -2.76356,-2.76356" />
<path
id="path6244-4"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 396.05076,217.93684 7.43329,7.43328 9.44882,-9.44881 9.44881,9.44881 9.44882,-9.44881 9.44882,9.44881 3.75961,-3.7596" />
<path
id="path6238-9"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 450.98792,234.55916 -0.25978,0.25978 -9.44882,-9.44882 -9.44882,9.44882 -9.44882,-9.44882 -9.44881,9.44882 -9.44882,-9.44882 -9.44882,9.44882 -7.32467,-7.32467" />
<path
id="path6232-0"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 377.2918,242.11356 7.29461,-7.29462 9.44882,9.44882 9.44882,-9.44882 9.44882,9.44882 9.44881,-9.44882 9.44882,9.44882 9.44882,-9.44882 9.44882,9.44882 3.23425,-3.23423" />
<path
id="path6226-9"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 459.4641,253.00372 -8.73596,-8.73596 -9.44882,9.44882 -9.44882,-9.44882 -9.44882,9.44882 -9.44881,-9.44882 -9.44882,9.44882 -9.44882,-9.44882 -6.0349,6.0349" />
<path
id="path6220-1"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 399.93928,259.62063 3.54477,3.54477 9.44882,-9.44882 9.44881,9.44882 9.44882,-9.44882 9.44882,9.44882 9.44882,-9.44882 9.44882,9.44882 2.71109,-2.71111" />
<path
id="path6214-7"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 471.31338,270.92662 -1.6876,1.6876 -9.44882,-9.44882 -9.44882,9.44882 -9.44882,-9.44882 -9.44882,9.44882 -9.44882,-9.44882 -9.44881,9.44882 -9.44882,-9.44882 -5.78649,5.78649" />
<path
id="path6208-7"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 469.69219,281.99664 5.21462,-5.21463" />
<path
id="path6206-1"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 469.59648,282.03374 0.0293,0.0293 0.0664,-0.0664" />
<path
id="path6204-1"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 418.49961,276.49629 3.88207,-3.88207 9.44882,9.44882 9.44882,-9.44882 9.44882,9.44882 9.44882,-9.44882 9.41952,9.41952" />
<path
id="path6198-5"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 455.79433,287.12923 -5.06619,-5.06619 -9.44882,9.44882 -9.44882,-9.44882 -9.44882,9.44882 -5.2552,-5.2552" />
<path
id="path6192-9"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 428.44588,294.89648 3.38462,-3.38462 9.44882,9.44882 9.44882,-9.44882 5.80835,5.80835" />
<path
id="path6186-7"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="m 443.64641,303.32776 -2.36709,-2.36708 -3.08189,3.08191" />
<path
id="path6391-7"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 416.48883,197.02367 h 17.24985" />
<path
id="path6385-6"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 442.42419,215.92132 -44.40396,-1e-5" />
<path
id="path6379-7"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 380.18051,234.81893 70.92719,1e-5" />
<path
id="path6373-3"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 459.79318,253.71658 H 401.26239" />
<path
id="path6367-6"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 408.27014,272.61422 h 65.51707" />
<path
id="path6361-5"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 451.65652,291.51186 -33.95677,-1e-5" />
<path
id="path6349-6"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 394.03522,251.74531 1e-5,-31.74616" />
<path
id="path6335-3"
style="fill:none;stroke:#ff0000;stroke-width:0.378;stroke-miterlimit:4;stroke-dasharray:none"
d="m 403.48406,210.32922 -2e-5,44.28524" />
<path
id="path6329-9"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 412.93287,274.2102 V 200.65927" />
<path
id="path6323-4"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 422.38168,190.99324 V 293.01688" />
<path
id="path6317-8"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 431.83051,300.63994 -1e-5,-107.76974" />
<path
id="path6311-1"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 441.27932,213.43274 v 90.35173" />
<path
id="path6305-2"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 450.72813,300.88603 10e-6,-66.89272" />
<path
id="path6299-9"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="m 460.17696,254.55391 v 30.1817" />
<path
id="path6293-3"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 469.62578,282.02076 V 269.98558" />
</g>
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 65.083241,4.8918538 18.973468,52.075943 c -15.579296,19.293065 10.602433,17.048329 21.826117,22.605253 4.02611,4.11535 -15.431707,7.152953 -11.405596,11.271736 4.02611,4.11535 24.345438,7.928656 28.378413,12.044007 4.02611,4.115351 -8.240998,8.481261 -4.214888,12.596611 4.02611,4.11535 13.337992,0.21624 15.08161,9.71689 1.242499,6.78913 16.780608,2.91748 24.379766,-2.64288 4.02611,-4.11878 -7.702128,-3.73093 -3.676018,-7.84628 10.012078,-10.23861 19.334258,-3.72064 22.759708,-13.979837 1.69213,-5.069536 -14.73838,-7.815391 -10.7054,-11.930741"
id="path2313" />
<path
d="m 54.048336,77.234841 c 1.232202,0.765407 19.869695,4.551255 24.424382,5.306366 1.578867,0.332934 0.459931,1.959854 -1.71616,3.058196 -4.908216,1.304281 -28.71478,-8.364562 -22.708222,-8.364562 z"
id="path2315"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 65.083242,4.8918543 C 53.499169,11.656955 13.461169,16.06062 32.459049,35.058506 l 47.795048,48.852196 c 5.84524,5.611842 15.599893,5.673624 21.143083,0"
id="path2322" />
<path
style="fill:none;stroke:#ff0000;stroke-width:0.378;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 65.083242,4.8918543 101.39718,83.910702"
id="path3130" />
<g
id="g11223">
<path
id="path6262"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 433.13709 195.71708 L 431.8305 197.02367 L 424.07106 189.26423 " />
<path
id="path6256"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 410.05994 203.59956 L 412.93287 206.47249 L 422.38168 197.02367 L 431.8305 206.47249 L 436.11352 202.18947 " />
<path
id="path6250"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 442.06249 215.13814 L 441.27932 215.92131 L 431.8305 206.47249 L 422.38168 215.92131 L 412.93287 206.47249 L 403.48405 215.92131 L 400.72049 213.15775 " />
<path
id="path6244"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 396.05076 217.93684 L 403.48405 225.37012 L 412.93287 215.92131 L 422.38168 225.37012 L 431.8305 215.92131 L 441.27932 225.37012 L 445.03893 221.61052 " />
<path
id="path6238"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 450.98792 234.55916 L 450.72814 234.81894 L 441.27932 225.37012 L 431.8305 234.81894 L 422.38168 225.37012 L 412.93287 234.81894 L 403.48405 225.37012 L 394.03523 234.81894 L 386.71056 227.49427 " />
<path
id="path6232"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 377.2918 242.11356 L 384.58641 234.81894 L 394.03523 244.26776 L 403.48405 234.81894 L 412.93287 244.26776 L 422.38168 234.81894 L 431.8305 244.26776 L 441.27932 234.81894 L 450.72814 244.26776 L 453.96239 241.03353 " />
<path
id="path6226"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 459.4641 253.00372 L 450.72814 244.26776 L 441.27932 253.71658 L 431.8305 244.26776 L 422.38168 253.71658 L 412.93287 244.26776 L 403.48405 253.71658 L 394.03523 244.26776 L 388.00033 250.30266 " />
<path
id="path6220"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 399.93928 259.62063 L 403.48405 263.1654 L 412.93287 253.71658 L 422.38168 263.1654 L 431.8305 253.71658 L 441.27932 263.1654 L 450.72814 253.71658 L 460.17696 263.1654 L 462.88805 260.45429 " />
<path
id="path6214"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 471.31338 270.92662 L 469.62578 272.61422 L 460.17696 263.1654 L 450.72814 272.61422 L 441.27932 263.1654 L 431.8305 272.61422 L 422.38168 263.1654 L 412.93287 272.61422 L 403.48405 263.1654 L 397.69756 268.95189 " />
<path
id="path6208"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 469.69219 281.99664 L 474.90681 276.78201 " />
<path
id="path6206"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 469.59648 282.03374 L 469.62578 282.06304 L 469.69219 281.99664 " />
<path
id="path6204"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 418.49961 276.49629 L 422.38168 272.61422 L 431.8305 282.06304 L 441.27932 272.61422 L 450.72814 282.06304 L 460.17696 272.61422 L 469.59648 282.03374 " />
<path
id="path6198"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 455.79433 287.12923 L 450.72814 282.06304 L 441.27932 291.51186 L 431.8305 282.06304 L 422.38168 291.51186 L 417.12648 286.25666 " />
<path
id="path6192"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 428.44588 294.89648 L 431.8305 291.51186 L 441.27932 300.96068 L 450.72814 291.51186 L 456.53649 297.32021 " />
<path
id="path6186"
style="fill:none;stroke:#0000ff;stroke-width:0.377953"
d="M 443.64641 303.32776 L 441.27932 300.96068 L 438.19743 304.04259 " />
<path
id="path6391"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 416.48883 197.02367 L 433.73868 197.02367 " />
<path
id="path6385"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 442.42419 215.92132 L 398.02023 215.92131 " />
<path
id="path6379"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 380.18051 234.81893 L 451.1077 234.81894 " />
<path
id="path6373"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 459.79318 253.71658 L 401.26239 253.71658 " />
<path
id="path6367"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 408.27014 272.61422 L 473.78721 272.61422 " />
<path
id="path6361"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 451.65652 291.51186 L 417.69975 291.51185 " />
<path
id="path6349"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 394.03522 251.74531 L 394.03523 219.99915 " />
<path
id="path6335"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 403.48406 210.32922 L 403.48404 254.61446 " />
<path
id="path6329"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 412.93287 274.2102 L 412.93287 200.65927 " />
<path
id="path6323"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 422.38168 190.99324 L 422.38168 293.01688 " />
<path
id="path6317"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 431.83051 300.63994 L 431.8305 192.8702 " />
<path
id="path6311"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 441.27932 213.43274 L 441.27932 303.78447 " />
<path
id="path6305"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 450.72813 300.88603 L 450.72814 233.99331 " />
<path
id="path6299"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 460.17696 254.55391 L 460.17696 284.73561 " />
<path
id="path6293"
style="fill:none;stroke:#ff0000;stroke-width:0.377953"
d="M 469.62578 282.02076 L 469.62578 269.98558 " />
</g>
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 464.53477,264.03673 c -4.03298,4.11535 12.39753,6.86121 10.7054,11.93074 -3.42546,10.2592 -12.74763,3.74123 -22.75971,13.97984 -4.02611,4.11535 7.70213,3.7275 3.67602,7.84628 -7.59916,5.56036 -23.13727,9.43201 -24.37977,2.64288 -1.74361,-9.50065 -11.0555,-5.60154 -15.08161,-9.71689 -4.02611,-4.11535 8.241,-8.48126 4.21489,-12.59661 -4.03297,-4.11535 -24.3523,-7.92866 -28.37841,-12.04401 -4.02611,-4.11878 15.4317,-7.15638 11.40559,-11.27173 -11.22368,-5.55693 -37.40541,-3.31219 -21.82611,-22.60526 l 46.10977,-47.18409 0,0 z"
id="path5392-9"
sodipodi:nodetypes="cccccscccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,21 @@
[
{
"name": "Origami Pattern - <various>",
"id": "fablabchemnitz.de.origami_patterns.<various>",
"path": "origami_patterns",
"dependent_extensions": null,
"original_name": "<various>",
"original_id": "org.inkscape.Origami_patterns.<various>",
"license": "MIT License",
"license_url": "https://github.com/evbernardes/Origami_Patterns/blob/master/LICENSE",
"comment": "",
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/origami_patterns",
"fork_url": "https://github.com/evbernardes/Origami_Patterns",
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Origami+Patterns",
"inkscape_gallery_url": null,
"main_authors": [
"github.com/evbernardes",
"github.com/vmario89"
]
}
]

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Masu box (width and height)</name>
<id>org.inkscape.Origami_patterns.boxes_masu</id>
<param name="active-tab" type="notebook">
<page name="title" gui-text="Options">
<param name="width" type="float" max="10000" precision="3" gui-text="Width of box">10.0</param>
<param name="height" type="float" max="10000" precision="3" gui-text="Height of box">10.0</param>
<label>Needs a square paper of size: sqrt(2) * (width + 2*height).</label>
<param name="width_delta" type="float" max="10000" precision="3" gui-text="Width increase*:">0.0</param>
<param name="width_delta_bool" type="bool" gui-text="Add width increase*">false</param>
<label>* this "width increase" slightly modifies the pattern for having a slightly bigger width and slightly smaller height, while keeping the same paper size. This is useful for creating companion box lids.</label>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Boxes" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Boxes_Masu.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Masu box (traditional)</name>
<id>org.inkscape.Origami_patterns.boxes_masu_traditional</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="length" type="float" max="10000" precision="3" gui-text="Length of square paper">10.0</param>
<label>Creates a box of width = length / (2 * ( sqrt(2)) and height = width / 2.</label>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Boxes" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Boxes_Masu_Traditional.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Bendy Straw</name>
<id>org.inkscape.Origami_patterns.cylindrical_bendy</id>
<param name="active-tab" type="notebook">
<page name="title" gui-text="Options">
<param name="pattern_type" type="optiongroup" appearance="combo" gui-text="Type of pattern:">
<option value="origami">Origami regular</option>
<option value="origami_bent">Origami bent</option>
<option value="kirigami1">Kirigami mode 1</option>
<option value="kirigami2">Kirigami mode 2</option>
</param>
<label>------------------------------------------------------------</label>
<param name="n" type="int" min="3" max="25" gui-text="Number of sides of polygon">6</param>
<param name="lines" type="int" min="1" max="100" gui-text="Number of cells">3</param>
<label>------------------------------------------------------------</label>
<param name="radius" type="float" max="10000" precision="3" gui-text="Radius of bigger polygon">25.0</param>
<param name="radial_ratio" type="float" max="1.0" min="0.0001" precision="3" gui-text="Ratio small radius/big radius">0.75</param>
<label>------------------------------------------------------------</label>
<param name="parameter_type" type="optiongroup" appearance="combo" gui-text="Parameter:">
<option value="angles">Angles (alpha1, alpha2)</option>
<option value="heights">Heights (h1, h2)</option>
</param>
<param name="alpha1" type="int" min="5" max="90" gui-text="Angle of superior cone (alpha1)">45</param>
<param name="alpha2" type="int" min="5" max="90" gui-text="Angle of inferior cone (alpha2)">35</param>
<param name="h1" type="float" min="0" max="200.0" precision="3" gui-text="Height of superior cone (h1)">1</param>
<param name="h2" type="float" min="0" max="200.0" precision="3" gui-text="Height of inferior cone (h2)">2</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<label>As published in: https://doi.org/10.1115/1.4052222</label>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="extra" gui-text="Extra">
<param name="add_attachment" type="bool" gui-text="Add attachments?">false</param>
<label>------------------------------------------------------------</label>
<param name="base_height" type="float" max="10000" precision="3" gui-text="Height of base">5.0</param>
<param name="add_base_slot" type="bool" gui-text="Add base slots?">false</param>
<param name="center_base_slot" type="bool" gui-text="Center base slots?">false</param>
<param name="base_slot_height" type="float" max="10000" precision="3" gui-text="Height of base slot">3.0</param>
<param name="base_slot_width" type="float" max="10000" precision="3" gui-text="Width of base slow">3.0</param>
<label>------------------------------------------------------------</label>
<param name="distance" type="float" max="10000" precision="3" gui-text="Distance between cells">3.0</param>
<param name="add_distance_slot" type="bool" gui-text="Add slots between cells?">false</param>
<param name="distance_slot_height" type="float" max="10000" precision="3" gui-text="Height of slots between cells">3.0</param>
<param name="distance_slot_width" type="float" max="10000" precision="3" gui-text="Width of slots between cells">3.0</param>
</page>
<page name="mountains" gui-text="Mountains">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valleys">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="cuts" gui-text="Cuts">
<param name="cut_bool" type="bool" gui-text="Draw cuts?">true</param>
<param name="cut_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="cut_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Cut dash + gap length">1</param>
<param name="cut_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Cut dash duty cycle">0.25</param>
<param name="cut_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of cut strokes">0.1</param>
<param name="cut_stroke_color" type="color" gui-text="Cut creases color: ">16711935</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_base_outer_bool" type="bool" gui-text="Outer base vertices?">true</param>
<param name="vertex_base_inner_bool" type="bool" gui-text="Other base vertices?">true</param>
<param name="vertex_radius_outer_bool" type="bool" gui-text="Outer radius vertices?">true</param>
<param name="vertex_radius_inner_bool" type="bool" gui-text="Inner radius vertices?">true</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Cylindrical" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Cylindrical_Bendy.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Kresling tower</name>
<id>org.inkscape.Origami_patterns.cylindrical_kresling</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="pattern" type="optiongroup" appearance="combo" gui-text="Type of Kresling tower">
<option value="regular">Regular</option>
<option value="mirrowed">Mirror odd cells</option>
</param>
<label>------------------------------------------------------------</label>
<param name="rows" type="int" min="1" max="100" gui-text="Number of cells">3</param>
<param name="sides" type="int" min="3" max="100" gui-text="Number of polygon sides">6</param>
<label>------------------------------------------------------------</label>
<param name="measure_value" type="float" max="10000" precision="3" gui-text="Measure value:">10.0</param>
<param name="measure_type" type="optiongroup" appearance="combo" gui-text="Measure type:">
<option value="a">Polygon side (a)</option>
<option value="b">Vertical mountain crease (b)</option>
<option value="l">Diagonal valley crease (l)</option>
<option value="radius_external">External radius</option>
<option value="radius_internal">Internal radius (totally closed)</option>
<option value="diameter_external">External diameter</option>
<option value="diameter_internal">Internal diameter (totally closed)</option>
</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
<label>------------------------------------------------------------</label>
<param name="parameter_type" type="optiongroup" appearance="combo" gui-text="Parameter type:">
<option value="angle_ratio">Angle ratio (lambda)</option>
<option value="radial_ratio">Radial ratio</option>
<option value="lambdatheta">Angle between a and l (lambda * theta)</option>
</param>
<param name="radial_ratio" type="float" min="0" max="0.7" precision="3" gui-text="Radial ratio:">0.5</param>
<param name="angle_ratio" type="float" min="0.5" max="1" precision="3" gui-text="Angle ratio:">0.5</param>
<param name="lambdatheta" type="float" min="15" max="90" precision="2" gui-text="Angle between a and l">60.0</param>
</page>
<page name="slots" gui-text="Slots">
<param name="extra_column" type="bool" gui-text="Extra column?">false</param>
<label>------------------------------------------------------------</label>
<param name="add_base_slot" type="bool" gui-text="Add base slots?">false</param>
<param name="base_slot_position" type="optiongroup" appearance="combo" gui-text="Base slot position:">
<option value="-1">Top</option>
<option value="0">Center</option>
<option value="1">Bottom</option>
</param>
<param name="base_height" type="float" max="10000" precision="3" gui-text="Height of base">5.0</param>
<param name="base_slot_height" type="float" max="10000" precision="3" gui-text="Height of base slot">3.0</param>
<param name="base_slot_width" type="float" max="10000" precision="3" gui-text="Width of base slow">3.0</param>
<label>------------------------------------------------------------</label>
<param name="add_middle_slot" type="bool" gui-text="Add slots between cells?">false</param>
<param name="middle_slot_position" type="optiongroup" appearance="combo" gui-text="Middle slot position:">
<option value="-1">Top</option>
<option value="0">Center</option>
<option value="1">Bottom</option>
</param>
<param name="distance" type="float" max="10000" precision="3" gui-text="Distance between cells">3.0</param>
<param name="middle_slot_height" type="float" max="10000" precision="3" gui-text="Height of slots between cells">3.0</param>
<param name="middle_slot_width" type="float" max="10000" precision="3" gui-text="Width of slots between cells">3.0</param>
</page>
<page name="cuts" gui-text="Cuts">
<param name="cut_bool" type="bool" gui-text="Draw cuts?">true</param>
<param name="cut_bool_only" type="bool" gui-text="Draw ONLY cuts?">true</param>
<param name="cut_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="cut_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Cut dash + gap length">1</param>
<param name="cut_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Cut dash duty cycle">0.25</param>
<param name="cut_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of cut strokes">0.1</param>
<param name="cut_stroke_color" type="color" gui-text="Cut creases color: ">16711935</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Cylindrical" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Cylindrical_Kresling.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>* Cylindrical template effect</name>
<id>org.inkscape.Origami_patterns.cylindrical_template</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<label>------------------------------------</label>
<label>Minimum necessary parameters for Cylindrical origami types :</label>
<param name="radius" type="float" max="10000" precision="3" gui-text="Radius of cylinder">10.0</param>
<param name="sides" type="int" min="3" max="25" gui-text="Number of sides of polygon">6</param>
<param name="rows" type="int" min="1" max="100" gui-text="Number of cells">3</param>
<label>-------------------------------------</label>
<param name="length" type="float" max="10000" precision="3" gui-text="Length">10.0</param>
<param name="angle" type="int" min="0" max="45" gui-text="Rotation angle (degree)">0</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<label>The .inx file defines the bridge between Inkscape's interface and the python script.</label>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="slots" gui-text="Slots">
<param name="extra_column" type="bool" gui-text="Extra column?">false</param>
<label>------------------------------------------------------------</label>
<param name="add_base_slot" type="bool" gui-text="Add base slots?">false</param>
<param name="base_slot_position" type="optiongroup" appearance="combo" gui-text="Base slot position:">
<option value="-1">Top</option>
<option value="0">Center</option>
<option value="1">Bottom</option>
</param>
<param name="base_height" type="float" max="10000" precision="3" gui-text="Height of base">5.0</param>
<param name="base_slot_height" type="float" max="10000" precision="3" gui-text="Height of base slot">3.0</param>
<param name="base_slot_width" type="float" max="10000" precision="3" gui-text="Width of base slow">3.0</param>
<label>------------------------------------------------------------</label>
<param name="add_middle_slot" type="bool" gui-text="Add slots between cells?">false</param>
<param name="middle_slot_position" type="optiongroup" appearance="combo" gui-text="Middle slot position:">
<option value="-1">Top</option>
<option value="0">Center</option>
<option value="1">Bottom</option>
</param>
<param name="distance" type="float" max="10000" precision="3" gui-text="Distance between cells">3.0</param>
<param name="middle_slot_height" type="float" max="10000" precision="3" gui-text="Height of slots between cells">3.0</param>
<param name="middle_slot_width" type="float" max="10000" precision="3" gui-text="Width of slots between cells">3.0</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Cylindrical" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Cylindrical_Template.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>* Support ring</name>
<id>org.inkscape.Origami_patterns.support_ring</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="sides" type="int" min="3" max="100" gui-text="Number of polygon sides">6</param>
<param name="radius_external" type="float" max="10000" precision="3" gui-text="Pattern radius:">10.0</param>
<param name="inverted" type="bool" gui-text="Invert hook direction?">false</param>
<param name="single_stroke" type="bool" gui-text="Single stroke?">true</param>
<label>------------------------------------------------------------</label>
<param name="connector_length" type="float" max="10000" precision="3" gui-text="Connector length:">3.0</param>
<param name="connector_thickness" type="float" max="10000" precision="3" gui-text="Connector thickness:">3.0</param>
<param name="head_length" type="float" max="10000" precision="3" gui-text="Head extra length:">1.0</param>
<param name="head_thickness" type="float" max="10000" precision="3" gui-text="Head extra thickness:">1.0</param>
<label>------------------------------------------------------------</label>
<param name="radius_draw" type="bool" gui-text="Draw internal radius? (or external, if inverted)">true</param>
<param name="radius_ratio" type="float" min="0" max="0.9" precision="3" gui-text="Radial ratio:">0.5</param>
<param name="radius_type" type="optiongroup" appearance="combo" gui-text="Internal radius type:">
<option value="polygonal">Polygonal</option>
<option value="circular">Circular</option>
</param>
<label>------------------------------------------------------------</label>
<label>Length must be at least the thickness of the origami material + the thickness of the belt.</label>
<label>For an OpenSCAD simple implementation of the belt, see Origami_Patterns/Support_Ring_Belt.</label>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
</page>
<page name="mountains" gui-text="Strokes">
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Strokes color: ">4278190335</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Cylindrical" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/SupportRing.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Bendy Straw (old, faster cutting)</name>
<id>org.inkscape.Origami_patterns.old_bendy</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="pattern_type" type="optiongroup" appearance="combo" gui-text="Type of pattern:">
<option value="origami">Origami regular</option>
<option value="origami_bent">Origami bent</option>
<option value="kirigami1">Kirigami mode 1</option>
<option value="kirigami2">Kirigami mode 2</option>
</param>
<label>------------------------------------------------------------</label>
<param name="n" type="int" min="3" max="25" gui-text="Number of sides of polygon">6</param>
<param name="lines" type="int" min="1" max="100" gui-text="Number of cells">3</param>
<label>------------------------------------------------------------</label>
<param name="radius" type="float" max="10000" precision="3" gui-text="Radius of bigger polygon">25.0</param>
<param name="radial_ratio" type="float" max="1.0" min="0.0001" precision="3" gui-text="Ratio small radius/big radius">0.75</param>
<label>------------------------------------------------------------</label>
<param name="parameter_type" type="optiongroup" appearance="combo" gui-text="Parameter:">
<option value="angles">Angles (alpha1, alpha2)</option>
<option value="heights">Heights (h1, h2)</option>
</param>
<param name="alpha1" type="int" min="5" max="90" gui-text="Angle of superior cone (alpha1)">45</param>
<param name="alpha2" type="int" min="5" max="90" gui-text="Angle of inferior cone (alpha2)">35</param>
<param name="h1" type="float" min="0" max="200.0" precision="3" gui-text="Height of superior cone (h1)">1</param>
<param name="h2" type="float" min="0" max="200.0" precision="3" gui-text="Height of inferior cone (h2)">2</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<label>As published in: https://doi.org/10.1115/1.4052222</label>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="extra" gui-text="Extra">
<param name="add_attachment" type="bool" gui-text="Add attachments?">false</param>
<label>------------------------------------------------------------</label>
<param name="base_height" type="float" max="10000" precision="3" gui-text="Height of base">5.0</param>
<param name="add_base_slot" type="bool" gui-text="Add base slots?">false</param>
<param name="center_base_slot" type="bool" gui-text="Center base slots?">false</param>
<param name="base_slot_height" type="float" max="10000" precision="3" gui-text="Height of base slot">3.0</param>
<param name="base_slot_width" type="float" max="10000" precision="3" gui-text="Width of base slow">3.0</param>
<label>------------------------------------------------------------</label>
<param name="distance" type="float" max="10000" precision="3" gui-text="Distance between cells">3.0</param>
<param name="add_distance_slot" type="bool" gui-text="Add slots between cells?">false</param>
<param name="distance_slot_height" type="float" max="10000" precision="3" gui-text="Height of slots between cells">3.0</param>
<param name="distance_slot_width" type="float" max="10000" precision="3" gui-text="Width of slots between cells">3.0</param>
</page>
<page name="mountains" gui-text="Mountains">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valleys">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="cuts" gui-text="Cuts">
<param name="cut_bool" type="bool" gui-text="Draw cuts?">true</param>
<param name="cut_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="cut_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Cut dash + gap length">1</param>
<param name="cut_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Cut dash duty cycle">0.25</param>
<param name="cut_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of cut strokes">0.1</param>
<param name="cut_stroke_color" type="color" gui-text="Cut creases color: ">16711935</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_base_outer_bool" type="bool" gui-text="Outer base vertices?">true</param>
<param name="vertex_base_inner_bool" type="bool" gui-text="Other base vertices?">true</param>
<param name="vertex_radius_outer_bool" type="bool" gui-text="Outer radius vertices?">true</param>
<param name="vertex_radius_inner_bool" type="bool" gui-text="Inner radius vertices?">true</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Deprecated" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Bendy.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Kresling tower (old)</name>
<id>org.inkscape.Origami_patterns.old_kresling</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="pattern" type="optiongroup" appearance="combo" gui-text="Type of Kresling tower">
<option value="regular">Regular</option>
<option value="mirrowed">Mirror odd cells</option>
</param>
<label>------------------------------------------------------------</label>
<param name="lines" type="int" min="1" max="100" gui-text="Number of cells">3</param>
<param name="sides" type="int" min="3" max="100" gui-text="Number of polygon sides">6</param>
<label>------------------------------------------------------------</label>
<param name="measure_value" type="float" max="10000" precision="3" gui-text="Measure value:">10.0</param>
<param name="measure_type" type="optiongroup" appearance="combo" gui-text="Measure type:">
<option value="a">Polygon side (a)</option>
<option value="b">Vertical mountain crease (b)</option>
<option value="l">Diagonal valley crease (l)</option>
<option value="radius_external">External radius</option>
<option value="radius_internal">Internal radius (totally closed)</option>
<option value="diameter_external">External diameter</option>
<option value="diameter_internal">Internal diameter (totally closed)</option>
</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<label>------------------------------------------------------------</label>
<param name="parameter_type" type="optiongroup" appearance="combo" gui-text="Parameter type:">
<option value="angle_ratio">Angle ratio (lambda)</option>
<option value="radial_ratio">Radial ratio</option>
<option value="lambdatheta">Angle between a and l (lambda * theta)</option>
</param>
<param name="radial_ratio" type="float" min="0" max="0.7" precision="3" gui-text="Radial ratio:">0.5</param>
<param name="angle_ratio" type="float" min="0.5" max="1" precision="3" gui-text="Angle ratio:">0.5</param>
<param name="lambdatheta" type="float" min="15" max="90" precision="2" gui-text="Angle between a and l">60.0</param>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="extraoptions" gui-text="Extra Options">
<param name="add_attachment" type="bool" gui-text="Add one more facet to close tower?">false</param>
<param name="attachment_percentage" type="float" min="0" max="100" precision="1" appearance="full" gui-text="Length percentage of extra facet">100</param>
<label>------------------------------------------------------------</label>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Deprecated" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Kresling_full.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Circular</name>
<id>org.inkscape.Origami_patterns.pleat_circular</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="radius" type="float" max="10000" precision="3" gui-text="Radius of circle">55.0</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<param name="ratio" type="float" min="0" max="1" precision="3" gui-text="Opening ratio">0.4</param>
<param name="rings" type="int" min="3" max="100" gui-text="Number of rings">15</param>
<label>------------------------------</label>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
<label>To simulate with OrigamiSimulator, semicreases (or facet creases) must be added to properly simulate paper, and the circles must be approximated as polygons.</label>
<param name="sides" type="int" min="10" max="100" gui-text="Number of sides for polygon approximating half circle">20</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
<page name="semicrease" gui-text="Semicreases">
<param name="semicrease_bool" type="bool" gui-text="Draw semicreases?">true</param>
<param name="semicrease_bool_only" type="bool" gui-text="Draw ONLY semicreases?">false</param>
<param name="semicrease_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="semicrease_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Semicrease dash + gap length">1</param>
<param name="semicrease_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Semicrease dash duty cycle">0.25</param>
<param name="semicrease_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of semicrease strokes">0.1</param>
<param name="semicrease_stroke_color" type="color" gui-text="Semicreases color: ">4294902015</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Pleat folds" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Pleat_Circular.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>N-sided Hypar</name>
<id>org.inkscape.Origami_patterns.pleat_hypar</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="pattern" type="optiongroup" appearance="combo" gui-text="Type of Hypar">
<option value="classic">Classic Hypar</option>
<option value="asymmetric">Asymmetric triangulation</option>
<option value="alternate_asymmetric">Alternating asymmetric triangulation</option>
</param>
<param name="radius" type="float" max="10000" precision="3" gui-text="Radius of polygon">100.0</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<param name="sides" type="int" min="3" max="100" gui-text="Number of polygon sides">4</param>
<param name="rings" type="int" min="1" max="100" gui-text="Number of rings">7</param>
<param name="simplify_center" type="bool" gui-text="Simplify center (probably not suited for odd number of sides)">false</param>
<label>Implements Hypar (classical hyperbolic paraboloid approximate). Classic Hypar is the easiest one to fold. However, it's not rigid foldable. More information in: Demaine, E. D., Demaine, M. L., Hart, V., Price, G. N., and Tachi, T. (2011). (Non)Existence of Pleated Folds: How Paper Folds Between Creases. Graphs and Combinatorics, 27(3), 377397. https://doi.org/10.1007/s00373-011-1025-2</label>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="universal" gui-text="Universal creases">
<param name="universal_bool" type="bool" gui-text="Draw universal creases?">true</param>
<param name="universal_bool_only" type="bool" gui-text="Draw ONLY universal creases?">false</param>
<param name="universal_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="universal_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Universal dash + gap length">1</param>
<param name="universal_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Universal dash duty cycle">0.25</param>
<param name="universal_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of universal strokes">0.1</param>
<param name="universal_stroke_color" type="color" gui-text="Universal creases color: ">4278255615</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="Pleat folds" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Hypar.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Template effect</name>
<id>org.inkscape.Origami_patterns.template</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="pattern" type="optiongroup" appearance="combo" gui-text="Type of template">
<option value="template1">Template pattern 1</option>
<option value="template2">Template pattern 2</option>
</param>
<param name="length" type="float" max="10000" precision="3" gui-text="Length of grid square">10.0</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<param name="angle" type="int" min="0" max="360" gui-text="Rotation angle (degree)">0</param>
<param name="fold_angle_valley" type="int" min="0" max="180" gui-text="Max fold angle of valleys (degree)">180</param>
<label>The .inx file defines the bridge between Inkscape's interface and the python script.</label>
<param name="simulation_mode" type="bool" gui-text="Simulation* mode">true</param>
<label>* Simulation mode bypasses most style preferences to quickly switch between OrigamiSimulator standard and your own chosen style (for laser cutting, for example).</label>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns">
<submenu name="* Template submenu" />
</submenu>
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Template.py</command>
</script>
</inkscape-extension>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Waterbomb</name>
<id>org.inkscape.Origami_patterns.magic_ball</id>
<param name="active-tab" type="notebook">
<page name="options" gui-text="Options">
<param name="pattern_first_line" type="optiongroup" appearance="combo" gui-text="First line:">
<option value="waterbomb">Regular waterbomb</option>
<option value="magic_ball">Magic ball</option>
</param>
<param name="pattern_last_line" type="optiongroup" appearance="combo" gui-text="Last line:">
<option value="waterbomb">Regular waterbomb</option>
<option value="magic_ball">Magic ball</option>
</param>
<param name="phase_shift" type="bool" gui-text="Shift phase?">false</param>
<label>------------------------------</label>
<param name="lines" type="int" min="1" max="100" gui-text="Number of lines">8</param>
<param name="columns" type="int" min="1" max="100" gui-text="Number of columns">16</param>
<label>------------------------------</label>
<param name="length" type="float" max="10000" precision="3" gui-text="Length of grid square">10.0</param>
<param name="units" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option>
<option value="cm">cm</option>
<option value="in">in</option>
<option value="pt">pt</option>
<option value="px">px</option>
</param>
<label>"Waterbomb tessellation" creates a simple tessellation pattern repeating the Waterbomb base, with a half-step phase shift between each line.
The Magic ball is a different design that inverts both the upper half of the first line and the bottom half of the last line.</label>
<param name="simulation_mode" type="bool" gui-text="Simulation mode">true</param>
</page>
<page name="mountains" gui-text="Mountain creases">
<param name="mountain_bool" type="bool" gui-text="Draw mountains?">true</param>
<param name="mountain_bool_only" type="bool" gui-text="Draw ONLY mountains?">false</param>
<param name="mountain_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="mountain_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Mountain dash + gap length">1</param>
<param name="mountain_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Mountain dash duty cycle">0.5</param>
<param name="mountain_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of mountain strokes">0.1</param>
<param name="mountain_stroke_color" type="color" gui-text="Mountain creases color: ">4278190335</param>
</page>
<page name="valleys" gui-text="Valley creases">
<param name="valley_bool" type="bool" gui-text="Draw valley?">true</param>
<param name="valley_bool_only" type="bool" gui-text="Draw ONLY valleys?">false</param>
<param name="valley_dashes_bool" type="bool" gui-text="Dashed strokes?">true</param>
<param name="valley_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Valley dash + gap length">1</param>
<param name="valley_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Valley dash duty cycle">0.25</param>
<param name="valley_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of valley strokes">0.1</param>
<param name="valley_stroke_color" type="color" gui-text="Valley creases color: ">65535</param>
</page>
<page name="edge" gui-text="Edge">
<param name="edge_bool" type="bool" gui-text="Draw edges?">true</param>
<param name="edge_bool_only" type="bool" gui-text="Draw ONLY edges?">false</param>
<param name="edge_single_path" type="bool" gui-text="Edges as single path?">true</param>
<param name="edge_dashes_bool" type="bool" gui-text="Dashed strokes?">false</param>
<param name="edge_dashes_len" type="float" min="0.1" max="10" appearance="full" precision="2" gui-text="Edge dash + gap length">1</param>
<param name="edge_dashes_duty" type="float" min="0.1" max="1" appearance="full" precision="2" gui-text="Edge dash duty cycle">0.25</param>
<param name="edge_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of edge strokes">0.1</param>
<param name="edge_stroke_color" type="color" gui-text="Edge color: ">255</param>
</page>
<page name="vertices" gui-text="Vertices">
<param name="vertex_bool" type="bool" gui-text="Draw vertices?">true</param>
<param name="vertex_bool_only" type="bool" gui-text="Draw ONLY vertices?">false</param>
<param name="vertex_radius" type="float" min="0.01" max="50" appearance="full" gui-text="Radius of vertices">0.1</param>
<param name="vertex_stroke_width" type="float" min="0.01" max="3" appearance="full" gui-text="Width of vertex strokes">0.1</param>
<param name="vertex_stroke_color" type="color" gui-text="Vertices\' color: ">255</param>
</page>
</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Origami Patterns" />
</effects-menu>
</effect>
<script>
<command location="inx" interpreter="python">OrigamiPatterns/Waterbomb.py</command>
</script>
</inkscape-extension>