added buxtronix living hinge extension
This commit is contained in:
parent
029169eb21
commit
968f5dbe6e
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="60mm"
|
||||
height="14mm"
|
||||
viewBox="0 0 60 14"
|
||||
version="1.1"
|
||||
id="svg961"
|
||||
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
|
||||
sodipodi:docname="diamond-lattice.svg">
|
||||
<defs
|
||||
id="defs955" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8484056"
|
||||
inkscape:cx="155.04988"
|
||||
inkscape:cy="77.608175"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1006"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="40"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata958">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 46.666285,12.224966 c 1.729044,0 4.034437,0.720435 5.76348,0.720435 1.729044,0 4.034437,-0.720435 5.763481,-0.720435"
|
||||
id="path5440" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 32.257584,12.224966 c 1.729044,0 4.034437,0.720435 5.76348,0.720435 1.729044,0 4.034437,-0.720435 5.763481,-0.720435"
|
||||
id="path5430" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 46.666285,9.3432239 c 1.729044,0 4.034437,0.7204361 5.76348,0.7204361 1.729044,0 4.034437,-0.7204361 5.763481,-0.7204361"
|
||||
id="path5390" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 46.666285,12.224966 c 1.729044,0 4.034437,-0.720435 5.76348,-0.720435 1.729044,0 4.034437,0.720435 5.763481,0.720435"
|
||||
id="path5388" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 59.634116,10.06366 c -1.729044,0 -4.034437,0.720435 -5.763481,0.720435 1.729044,0 4.034437,0.720435 5.763481,0.720435"
|
||||
id="path5386" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 45.225415,10.06366 c 1.729044,0 4.034437,0.720435 5.763481,0.720435 -1.729044,0 -4.034437,0.720435 -5.763481,0.720435"
|
||||
id="path5384" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="M 45.225415,9.3432239"
|
||||
id="path5382" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 32.257584,9.3432239 c 1.729044,0 4.034437,0.7204361 5.76348,0.7204361 1.729044,0 4.034437,-0.7204361 5.763481,-0.7204361"
|
||||
id="path5380" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 32.257584,12.224966 c 1.729044,0 4.034437,-0.720435 5.76348,-0.720435 1.729044,0 4.034437,0.720435 5.763481,0.720435"
|
||||
id="path5378" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 45.225415,10.06366 c -1.729044,0 -4.034437,0.720435 -5.763481,0.720435 1.729044,0 4.034437,0.720435 5.763481,0.720435"
|
||||
id="path5376" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 30.816714,10.06366 c 1.729044,0 4.034437,0.720435 5.763481,0.720435 -1.729044,0 -4.034437,0.720435 -5.763481,0.720435"
|
||||
id="path5374" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="M 30.816714,9.3432239"
|
||||
id="path5372" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 46.666285,6.4614845 c 1.729044,0 4.034437,0.720435 5.76348,0.720435 1.729044,0 4.034437,-0.720435 5.763481,-0.720435"
|
||||
id="path5340" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 46.666285,9.3432239 c 1.729044,0 4.034437,-0.7204345 5.76348,-0.7204345 1.729044,0 4.034437,0.7204345 5.763481,0.7204345"
|
||||
id="path5338" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 59.634116,7.1819195 c -1.729044,0 -4.034437,0.7204349 -5.763481,0.7204349 1.729044,0 4.034437,0.720435 5.763481,0.720435"
|
||||
id="path5336" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 45.225415,7.1819195 c 1.729044,0 4.034437,0.7204349 5.763481,0.7204349 -1.729044,0 -4.034437,0.720435 -5.763481,0.720435"
|
||||
id="path5334" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="M 45.225415,6.4614845"
|
||||
id="path5332" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 32.257584,6.4614845 c 1.729044,0 4.034437,0.720435 5.76348,0.720435 1.729044,0 4.034437,-0.720435 5.763481,-0.720435"
|
||||
id="path5330" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 32.257584,9.3432239 c 1.729044,0 4.034437,-0.7204345 5.76348,-0.7204345 1.729044,0 4.034437,0.7204345 5.763481,0.7204345"
|
||||
id="path5328" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 45.225415,7.1819195 c -1.729044,0 -4.034437,0.7204349 -5.763481,0.7204349 1.729044,0 4.034437,0.720435 5.763481,0.720435"
|
||||
id="path5326" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="m 30.816714,7.1819195 c 1.729044,0 4.034437,0.7204349 5.763481,0.7204349 -1.729044,0 -4.034437,0.720435 -5.763481,0.720435"
|
||||
id="path5324" />
|
||||
<path
|
||||
id="path892"
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.144087"
|
||||
d="M 30.333099,5.2546335 M 0.54402462,0.32757335 m 0,0.68989875 c 0,0 5.51918898,0.6898986 5.51918898,0.6898986 0,0 -5.51918898,0.6898986 -5.51918898,0.6898986 M 14.341997,1.0174721 c 0,0 -5.5191888,0.6898986 -5.5191888,0.6898986 0,0 5.5191888,0.6898986 5.5191888,0.6898986 M 1.9238218,3.087168 c 0,0 5.5191892,-0.6898987 5.5191892,-0.6898987 0,0 5.519189,0.6898987 5.519189,0.6898987 M 1.9238218,0.32757335 c 0,0 5.5191892,0.68989875 5.5191892,0.68989875 0,0 5.519189,-0.68989875 5.519189,-0.68989875 m 1.379797,0 m 0,0.68989875 c 0,0 5.519189,0.6898986 5.519189,0.6898986 0,0 -5.519189,0.6898986 -5.519189,0.6898986 M 28.13997,1.0174721 c 0,0 -5.519189,0.6898986 -5.519189,0.6898986 0,0 5.519189,0.6898986 5.519189,0.6898986 M 15.721795,3.087168 c 0,0 5.519189,-0.6898987 5.519189,-0.6898987 0,0 5.519189,0.6898987 5.519189,0.6898987 M 15.721795,0.32757335 c 0,0 5.519189,0.68989875 5.519189,0.68989875 0,0 5.519189,-0.68989875 5.519189,-0.68989875 m 1.379797,0 m 0,0.68989875 c 0,0 5.519189,0.6898986 5.519189,0.6898986 0,0 -5.519189,0.6898986 -5.519189,0.6898986 M 0.54402462,3.087168 m 0,0.6898986 c 0,0 5.51918898,0.6898986 5.51918898,0.6898986 0,0 -5.51918898,0.6898987 -5.51918898,0.6898987 M 14.341997,3.7770666 c 0,0 -5.5191888,0.6898986 -5.5191888,0.6898986 0,0 5.5191888,0.6898987 5.5191888,0.6898987 M 1.9238218,5.8467625 c 0,0 5.5191892,-0.6898986 5.5191892,-0.6898986 0,0 5.519189,0.6898986 5.519189,0.6898986 M 1.9238218,3.087168 c 0,0 5.5191892,0.6898986 5.5191892,0.6898986 0,0 5.519189,-0.6898986 5.519189,-0.6898986 m 1.379797,0 m 0,0.6898986 c 0,0 5.519189,0.6898986 5.519189,0.6898986 0,0 -5.519189,0.6898987 -5.519189,0.6898987 M 28.13997,3.7770666 c 0,0 -5.519189,0.6898986 -5.519189,0.6898986 0,0 5.519189,0.6898987 5.519189,0.6898987 M 15.721795,5.8467625 c 0,0 5.519189,-0.6898986 5.519189,-0.6898986 0,0 5.519189,0.6898986 5.519189,0.6898986 M 15.721795,3.087168 c 0,0 5.519189,0.6898986 5.519189,0.6898986 0,0 5.519189,-0.6898986 5.519189,-0.6898986 m 1.379797,0 m 0,0.6898986 c 0,0 5.519189,0.6898986 5.519189,0.6898986 0,0 -5.519189,0.6898987 -5.519189,0.6898987" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 852 B |
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Buxtronix Living Hinges</name>
|
||||
<id>fablabchemnitz.de.buxtronix_living_hinges</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="straight_lattice" gui-text="Straight lattice">
|
||||
<image>images/straight-lattice.png</image>
|
||||
<param name="sl_length" type="int" min="1" max="200" gui-text="Length of elements" appearance="full">20</param>
|
||||
<param name="sl_spacing" type="float" min="0.1" max="10.0" precision="1" gui-text="Vertical element spacing" appearance="full">2.0</param>
|
||||
<param name="sl_gap" type="float" min="0.0" max="10.0" precision="1" gui-text="Element height" appearance="full">0.0</param>
|
||||
<label xml:space="preserve">
|
||||
</label>
|
||||
</page>
|
||||
<page name="diamond_lattice" gui-text="Diamond lattice">
|
||||
<image>images/diamond-lattice.png</image>
|
||||
<param name="dl_length" type="int" min="1" max="200" gui-text="Length of elements" appearance="full">20</param>
|
||||
<param name="dl_spacing" type="float" min="0.1" max="10.0" precision="1" gui-text="Vertical element spacing" appearance="full">4.0</param>
|
||||
<param name="dl_curve" type="float" min="-1.0" max="1.0" precision="1" gui-text="Curve of each element" appearance="full">0.5</param>
|
||||
<label xml:space="preserve">
|
||||
</label>
|
||||
</page>
|
||||
<page name="cross_lattice" gui-text="Cross lattice">
|
||||
<image>images/cross-lattice.png</image>
|
||||
<param name="cl_length" type="int" min="1" max="200" gui-text="Length of elements" appearance="full">20</param>
|
||||
<param name="cl_spacing" type="float" min="0.1" max="10.0" precision="1" gui-text="Vertical element spacing" appearance="full">6.0</param>
|
||||
<label xml:space="preserve">
|
||||
</label>
|
||||
</page>
|
||||
<page name="wavy_lattice" gui-text="Wavy lattice">
|
||||
<image>images/wavy-lattice.png</image>
|
||||
<param name="wl_length" type="int" min="1" max="200" gui-text="Length of elements" appearance="full">29</param>
|
||||
<param name="wl_spacing" type="float" min="0.1" max="10.0" precision="1" gui-text="Vertical element spacing" appearance="full">4.0</param>
|
||||
<label xml:space="preserve">
|
||||
</label>
|
||||
</page>
|
||||
<page name="about" gui-text="About/Help">
|
||||
<label xml:space="preserve">
|
||||
This extension renders Living Hinges, aka lattice hinges aka laser kerf bending.
|
||||
|
||||
These patterns allow otherwise rigid materials (eg wood, acrylic) to have bends formed in them.
|
||||
</label>
|
||||
<image>images/about.png</image>
|
||||
<label appearance="url">https://github.com/buxtronix/living-hinge</label>
|
||||
</page>
|
||||
</param>
|
||||
<param name="width" type="float" min="0" max="10000" gui-text="Width">100</param>
|
||||
<param name="height" type="float" min="0" max="10000" gui-text="Height">100</param>
|
||||
<param name="unit" gui-text="Unit for width/height" type="optiongroup" appearance="minimal">
|
||||
<option value="mm">mm</option>
|
||||
<option value="cm">cm</option>
|
||||
<option value="in">in</option>
|
||||
</param>
|
||||
<label>If any object(s) are currently selected, their bounding boxes will be filled with the pattern
|
||||
instead of using the above Width/Height. Slider dimensions are all millimetres.</label>
|
||||
<separator />
|
||||
<param name="swatch" type="boolean" gui-text="Draw swatch card">false</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Shape/Pattern from Generator"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command reldir="inx" interpreter="python">living_hinge.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
450
extensions/fablabchemnitz/buxtronix_living_hinge/living_hinge.py
Executable file
450
extensions/fablabchemnitz/buxtronix_living_hinge/living_hinge.py
Executable file
@ -0,0 +1,450 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import inkex
|
||||
cut_colour = '#ff0000'
|
||||
engrave_colour = '#0000ff'
|
||||
|
||||
class Generator(object):
|
||||
"""A generic generator, subclassed for each different lattice style."""
|
||||
|
||||
def __init__(self, x, y, width, height, stroke_width, svg, e_length, p_spacing):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.stroke_width = stroke_width
|
||||
self.svg = svg
|
||||
self.canvas = self.svg.get_current_layer()
|
||||
self.e_length = e_length
|
||||
self.e_height = 0 # Provided by sub-classes.
|
||||
self.p_spacing = p_spacing
|
||||
self.fixed_commands = ""
|
||||
|
||||
def draw_one(self, x, y):
|
||||
return "M %f,%f %s" % (x, y, self.fixed_commands)
|
||||
|
||||
def parameter_text(self):
|
||||
return "length: %.f spacing: %.1f" % (
|
||||
self.e_length,
|
||||
self.p_spacing,
|
||||
)
|
||||
|
||||
def draw_swatch(self):
|
||||
border = self.canvas.add(inkex.PathElement())
|
||||
# Curve radius
|
||||
cr = self.svg.unittouu('10mm')
|
||||
# Swatch padding
|
||||
sp = self.svg.unittouu('30mm')
|
||||
# Handle length
|
||||
hl = cr/2
|
||||
path_command = (
|
||||
'm %f,%f l %f,%f c %f,%f %f,%f %f,%f'
|
||||
'l %f,%f c %f,%f %f,%f %f,%f '
|
||||
'l %f,%f c %f,%f %f,%f %f,%f '
|
||||
'l %f,%f c %f,%f %f,%f %f,%f ') % (
|
||||
cr, 0,
|
||||
|
||||
self.width - 2*cr, 0,
|
||||
|
||||
hl, 0,
|
||||
cr, cr-hl,
|
||||
cr, cr,
|
||||
|
||||
0, self.height - 2*cr + 1.5*sp,
|
||||
|
||||
0, cr/2,
|
||||
0-cr+hl, cr,
|
||||
0-cr, cr,
|
||||
|
||||
0-self.width + 2*cr, 0,
|
||||
|
||||
0-hl, 0,
|
||||
0-cr, 0-cr+hl,
|
||||
0-cr, 0-cr,
|
||||
|
||||
0, 0-self.height - 1.5*sp + 2*cr,
|
||||
|
||||
0, 0-hl,
|
||||
cr-hl, 0-cr,
|
||||
cr, 0-cr
|
||||
)
|
||||
|
||||
style = {
|
||||
"stroke": cut_colour,
|
||||
"stroke-width": str(self.stroke_width),
|
||||
"fill": "none",
|
||||
}
|
||||
border.update(**{"style": style, "inkscape:label": "lattice_border", "d": path_command})
|
||||
|
||||
c = self.canvas.add(inkex.Circle(
|
||||
style=str(inkex.Style(style)),
|
||||
cx=str(cr),
|
||||
cy=str(cr),
|
||||
r=str(self.svg.unittouu('4mm'))))
|
||||
|
||||
self.y += sp
|
||||
|
||||
text_style = {
|
||||
'fill': engrave_colour,
|
||||
'font-size': '9px',
|
||||
'font-family': 'sans-serif',
|
||||
'text-anchor': 'middle',
|
||||
'text-align': 'center',
|
||||
}
|
||||
text = self.canvas.add(
|
||||
inkex.TextElement(
|
||||
style=str(inkex.Style(text_style)),
|
||||
x=str(self.x + self.width/2),
|
||||
y=str(self.y - sp/2)))
|
||||
text.text = "Style: %s" % self.name
|
||||
|
||||
text_style['font-size'] = "3px"
|
||||
text = self.canvas.add(
|
||||
inkex.TextElement(
|
||||
style=str(inkex.Style(text_style)),
|
||||
x=str(self.x + self.width/2),
|
||||
y=str(self.y - sp/4)))
|
||||
text.text = self.parameter_text()
|
||||
|
||||
text = self.canvas.add(
|
||||
inkex.TextElement(
|
||||
style=str(inkex.Style(text_style)),
|
||||
x=str(self.x + self.width/2),
|
||||
y=str(self.y +self.height + sp/4)))
|
||||
text.text = "https://github.com/buxtronix/living-hinge"
|
||||
|
||||
def generate(self, swatch):
|
||||
if swatch:
|
||||
self.draw_swatch()
|
||||
# Round width/height to integer number of patterns.
|
||||
self.e_length = self.width / max(round(self.width / self.e_length), 1.0)
|
||||
self.e_height = self.height / max(round(self.height / self.e_height), 1.0)
|
||||
self.prerender()
|
||||
style = {
|
||||
"stroke": cut_colour,
|
||||
"stroke-width": str(self.stroke_width),
|
||||
"fill": "none",
|
||||
}
|
||||
path_command = ""
|
||||
y = self.y
|
||||
while y < self.y + self.height:
|
||||
x = self.x
|
||||
while x < self.x + self.width:
|
||||
path_command = "%s %s " % (path_command, self.draw_one(x, y))
|
||||
x += self.e_length
|
||||
y += self.e_height
|
||||
|
||||
link = self.canvas.add(inkex.PathElement())
|
||||
link.update(**{"style": style, "inkscape:label": "lattice", "d": path_command})
|
||||
link.description("%s hinge %s" % (self.name, self.parameter_text()))
|
||||
|
||||
|
||||
class StraightLatticeGenerator(Generator):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StraightLatticeGenerator, self).__init__(*args)
|
||||
self.link_gap = kwargs['link_gap']
|
||||
self.e_height = 2 * self.p_spacing
|
||||
self.name = "straight"
|
||||
|
||||
def prerender(self):
|
||||
self.e_height = 2 * self.p_spacing
|
||||
w = self.e_length
|
||||
lg = self.link_gap
|
||||
|
||||
if lg < 0.1:
|
||||
# Single line for 0 height gap.
|
||||
self.fixed_commands = " m %f,%f h %f m %f,%f h %f m %f,%f h %f" % (
|
||||
0, self.e_height / 2,
|
||||
w * 2 / 5,
|
||||
|
||||
0 - w / 5, 0 - self.e_height / 2,
|
||||
w * 3 / 5,
|
||||
|
||||
0 - w / 5, self.e_height / 2,
|
||||
w * 2 / 5,
|
||||
)
|
||||
else:
|
||||
self.fixed_commands = (
|
||||
" m %f,%f h %f v %f h %f"
|
||||
" m %f,%f h %f v %f h %f v %f"
|
||||
" m %f,%f h %f v %f h %f "
|
||||
) % (
|
||||
0,
|
||||
self.e_height / 2,
|
||||
w * 2 / 5,
|
||||
lg,
|
||||
0 - w * 2 / 5,
|
||||
w / 8,
|
||||
0 - lg - self.e_height / 2,
|
||||
w * 3 / 4,
|
||||
lg,
|
||||
0 - w * 3 / 4,
|
||||
0 - lg,
|
||||
w * 7 / 8,
|
||||
lg + self.e_height / 2,
|
||||
0 - w * 2 / 5,
|
||||
0 - lg,
|
||||
w * 2 / 5,
|
||||
)
|
||||
|
||||
def parameter_text(self):
|
||||
text = super(StraightLatticeGenerator, self).parameter_text()
|
||||
return "%s element_height: %.1f" % (text, self.link_gap)
|
||||
|
||||
|
||||
class DiamondLatticeGenerator(Generator):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DiamondLatticeGenerator, self).__init__(*args)
|
||||
self.e_height = self.p_spacing
|
||||
self.diamond_curve = kwargs['diamond_curve']
|
||||
self.name = "diamond"
|
||||
|
||||
def prerender(self):
|
||||
h = self.e_height
|
||||
w = self.e_length
|
||||
# Diamond curve
|
||||
dc = 0-self.diamond_curve
|
||||
# Horiz handle length.
|
||||
hhl = abs(dc * w * 0.2)
|
||||
# Endpoint horiz handle length
|
||||
ehhl = hhl if dc > 0 else 0
|
||||
# Vert handle length
|
||||
vhl = abs(dc * h / 8) if dc < 0 else 0
|
||||
# Left
|
||||
self.fixed_commands = " m %f,%f c %f,%f %f,%f %f,%f c %f,%f %f,%f %f,%f " % (
|
||||
0, h / 4,
|
||||
|
||||
hhl, 0,
|
||||
w * 0.4 - ehhl, h / 4 - vhl,
|
||||
w * 0.4, h / 4,
|
||||
|
||||
0 - ehhl, vhl,
|
||||
0 - (w * 0.4 - hhl), h / 4,
|
||||
0 - w * 0.4, h / 4,
|
||||
)
|
||||
|
||||
# Bottom
|
||||
self.fixed_commands = "%s m %f,%f c %f,%f %f,%f %f,%f s %f,%f %f,%f " % (
|
||||
self.fixed_commands,
|
||||
w * 0.1, h / 4,
|
||||
|
||||
ehhl, 0 - vhl,
|
||||
w * 0.4 - hhl, 0 - h / 4,
|
||||
w * 0.4, 0 - h / 4,
|
||||
|
||||
w * 0.4 - ehhl, h / 4 - vhl,
|
||||
w * 0.4, h / 4,
|
||||
)
|
||||
|
||||
# Top
|
||||
self.fixed_commands = "%s m %f,%f c %f,%f %f,%f %f,%f s %f,%f %f,%f " % (
|
||||
self.fixed_commands,
|
||||
0 - w * 0.8, 0 - h,
|
||||
|
||||
ehhl, vhl,
|
||||
w * 0.4 - hhl, h / 4,
|
||||
w * 0.4, h / 4,
|
||||
|
||||
w * 0.4 - ehhl, 0 - h / 4 + vhl,
|
||||
w * 0.4, 0 - h / 4,
|
||||
)
|
||||
|
||||
# Right
|
||||
self.fixed_commands = "%s m %f,%f c %f,%f %f,%f %f,%f c %f,%f %f,%f %f,%f " % (
|
||||
self.fixed_commands,
|
||||
w * 0.1, h *0.75,
|
||||
|
||||
0 - hhl, 0,
|
||||
(0 - w * 0.4) + ehhl, 0 - h / 4 + vhl,
|
||||
0 - w * 0.4, 0 - h / 4,
|
||||
|
||||
ehhl, 0 - vhl,
|
||||
w * 0.4 - hhl, 0 - h / 4,
|
||||
w * 0.4, 0 - h / 4,
|
||||
)
|
||||
|
||||
def draw_one(self, x, y):
|
||||
return "M %f,%f %s" % (x, y, self.fixed_commands)
|
||||
|
||||
def parameter_text(self):
|
||||
text = super(DiamondLatticeGenerator, self).parameter_text()
|
||||
return "%s curve: %.1f" % (text, self.diamond_curve)
|
||||
|
||||
|
||||
class CrossLatticeGenerator(Generator):
|
||||
def __init__(self, *args):
|
||||
super(CrossLatticeGenerator, self).__init__(*args)
|
||||
self.e_height = self.p_spacing
|
||||
self.name = "cross"
|
||||
|
||||
def prerender(self):
|
||||
l = self.e_length
|
||||
h = self.e_height
|
||||
self.fixed_commands = (
|
||||
"m %f,%f l %f,%f l %f,%f m %f,%f l %f,%f"
|
||||
"m %f,%f l %f,%f l %f,%f l %f,%f "
|
||||
"m %f,%f l %f,%f l %f,%f l %f,%f "
|
||||
"m %f,%f l %f,%f l %f,%f m %f,%f l %f,%f"
|
||||
) % (
|
||||
# Left
|
||||
0, h * 0.5,
|
||||
l * 0.2, 0,
|
||||
l * 0.2, 0 - h * 0.3,
|
||||
0 - l * 0.2, h * 0.3,
|
||||
l * 0.2, h * 0.3,
|
||||
# Top
|
||||
0 - l * 0.3, 0 - h * 0.5,
|
||||
l * 0.2, 0 - h * 0.3,
|
||||
l * 0.4, 0,
|
||||
l * 0.2, h * 0.3,
|
||||
# Bottom
|
||||
0, h * 0.4,
|
||||
0 - l * 0.2, h * 0.3,
|
||||
0 - l * 0.4, 0,
|
||||
0 - l * 0.2, 0 - h * 0.3,
|
||||
# Right
|
||||
l * 0.5, 0 - h * 0.5,
|
||||
l * 0.2, h * 0.3,
|
||||
0 - l * 0.2, h * 0.3,
|
||||
l * 0.2, 0 - h * 0.3,
|
||||
l * 0.2, 0,
|
||||
)
|
||||
|
||||
|
||||
class WavyLatticeGenerator(Generator):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WavyLatticeGenerator, self).__init__(*args)
|
||||
self.e_height = self.p_spacing
|
||||
self.name = "wavy"
|
||||
|
||||
def prerender(self):
|
||||
h = self.e_height
|
||||
w = self.e_length
|
||||
self.fixed_commands = (
|
||||
" m %f,%f h %f c %f,%f %f,%f %f,%f h %f "
|
||||
"m %f,%f h %f c %f,%f %f,%f %f,%f h %f "
|
||||
) % (
|
||||
0, h, # Start of element (left)
|
||||
w * 0.1, # Short horiz line.
|
||||
|
||||
w * 0.1, 0, # Control 1
|
||||
w * 3 / 40, 0 - h / 2, # Control 2
|
||||
w * 0.2, 0 - h / 2, # Curve top.
|
||||
|
||||
w * 0.175, # Top horiz line.
|
||||
|
||||
0 - w * 0.1, 0 - h / 2, # Move to higher line.
|
||||
w * 0.3, # Long higher horiz line.
|
||||
|
||||
w / 5, 0, # Control 1
|
||||
w / 10, h, # Control 2
|
||||
w * 0.25, h, # Curve down.
|
||||
|
||||
w * 0.075, # End horiz line.
|
||||
)
|
||||
|
||||
|
||||
class LivingHingeEffect(inkex.EffectExtension):
|
||||
"""
|
||||
Extension to create laser cut bend lattices.
|
||||
"""
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--tab", help="Bend pattern to generate")
|
||||
pars.add_argument("--unit", help="Units for dimensions")
|
||||
pars.add_argument("--swatch", type=inkex.Boolean, help="Draw as a swatch card")
|
||||
|
||||
pars.add_argument("--width", type=float, default=300, help="Width of pattern")
|
||||
pars.add_argument("--height", type=float, default=100, help="Height of pattern")
|
||||
|
||||
pars.add_argument("--sl_length", type=int, default=20, help="Length of links")
|
||||
pars.add_argument("--sl_gap", type=float, default=0.5, help="Gap between links")
|
||||
pars.add_argument("--sl_spacing", type=float, default=20, help="Spacing of links")
|
||||
|
||||
pars.add_argument("--dl_curve", type=float, default=0.5, help="Curve of diamonds")
|
||||
pars.add_argument("--dl_length", type=float, default=24, help="Length of diamonds")
|
||||
pars.add_argument("--dl_spacing", type=float, default=4, help="Spacing of diamonds")
|
||||
|
||||
pars.add_argument("--cl_length", type=float, default=24, help="Length of combs")
|
||||
pars.add_argument("--cl_spacing", type=float, default=6, help="Spacing of combs")
|
||||
|
||||
pars.add_argument("--wl_length", type=int, default=20, help="Length of links")
|
||||
pars.add_argument("--wl_interval", type=int, default=30, help="Interval between links")
|
||||
pars.add_argument("--wl_spacing", type=float, default=0.5, help="Spacing between links")
|
||||
|
||||
def convert(self, value):
|
||||
return self.svg.unittouu(str(value) + self.options.unit)
|
||||
|
||||
def convertmm(self, value):
|
||||
return self.svg.unittouu('%fmm' % value)
|
||||
|
||||
def effect(self):
|
||||
stroke_width = self.svg.unittouu("0.2mm")
|
||||
self.options.width = self.convert(self.options.width)
|
||||
self.options.height = self.convert(self.options.height)
|
||||
|
||||
def draw_one(x, y):
|
||||
if self.options.tab == "straight_lattice":
|
||||
generator = StraightLatticeGenerator(
|
||||
x,
|
||||
y,
|
||||
self.options.width,
|
||||
self.options.height,
|
||||
stroke_width,
|
||||
self.svg,
|
||||
self.convertmm(self.options.sl_length),
|
||||
self.convertmm(self.options.sl_spacing),
|
||||
link_gap=self.convertmm(self.options.sl_gap),
|
||||
)
|
||||
elif self.options.tab == "diamond_lattice":
|
||||
generator = DiamondLatticeGenerator(
|
||||
x,
|
||||
y,
|
||||
self.options.width,
|
||||
self.options.height,
|
||||
stroke_width,
|
||||
self.svg,
|
||||
self.convertmm(self.options.dl_length),
|
||||
self.convertmm(self.options.dl_spacing),
|
||||
diamond_curve=self.options.dl_curve,
|
||||
)
|
||||
elif self.options.tab == "cross_lattice":
|
||||
generator = CrossLatticeGenerator(
|
||||
x,
|
||||
y,
|
||||
self.options.width,
|
||||
self.options.height,
|
||||
stroke_width,
|
||||
self.svg,
|
||||
self.convertmm(self.options.cl_length),
|
||||
self.convertmm(self.options.cl_spacing),
|
||||
)
|
||||
elif self.options.tab == "wavy_lattice":
|
||||
generator = WavyLatticeGenerator(
|
||||
x,
|
||||
y,
|
||||
self.options.width,
|
||||
self.options.height,
|
||||
stroke_width,
|
||||
self.svg,
|
||||
self.convertmm(self.options.wl_length),
|
||||
self.convertmm(self.options.wl_spacing),
|
||||
)
|
||||
else:
|
||||
inkex.errormsg("Select a valid pattern tab before rendering.")
|
||||
return
|
||||
generator.generate(self.options.swatch)
|
||||
|
||||
if self.options.swatch or not self.svg.selected:
|
||||
draw_one(0, 0)
|
||||
else:
|
||||
for elem in self.svg.selected.values():
|
||||
# Determine width and height based on the selected object's bounding box.
|
||||
bbox = elem.bounding_box()
|
||||
self.options.width = bbox.width
|
||||
self.options.height = bbox.height
|
||||
x = bbox.x.minimum
|
||||
y = bbox.y.minimum
|
||||
draw_one(x, y)
|
||||
|
||||
LivingHingeEffect().run()
|
Reference in New Issue
Block a user