summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaalleen <36401965+kaalleen@users.noreply.github.com>2023-03-15 20:41:54 +0100
committerGitHub <noreply@github.com>2023-03-15 20:41:54 +0100
commit0b0704c300efedd88fb4691b3d3cffc341fa3476 (patch)
treeba5fafdc377011644cab9ed004c42e3ba5cfb344
parentc92b4959179da8e030599e00250dcee728b392af (diff)
Zigzag line to satin (#2131)
-rw-r--r--lib/extensions/__init__.py2
-rw-r--r--lib/extensions/zigzag_line_to_satin.py145
-rw-r--r--templates/zigzag_line_to_satin.xml43
3 files changed, 190 insertions, 0 deletions
diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py
index fc70fcef..cc47f151 100644
--- a/lib/extensions/__init__.py
+++ b/lib/extensions/__init__.py
@@ -33,6 +33,7 @@ from .lettering_force_lock_stitches import LetteringForceLockStitches
from .lettering_generate_json import LetteringGenerateJson
from .lettering_remove_kerning import LetteringRemoveKerning
from .letters_to_font import LettersToFont
+from .zigzag_line_to_satin import ZigzagLineToSatin
from .object_commands import ObjectCommands
from .object_commands_toggle_visibility import ObjectCommandsToggleVisibility
from .output import Output
@@ -73,6 +74,7 @@ __all__ = extensions = [StitchPlanPreview,
CommandsScaleSymbols,
ConvertToSatin,
StrokeToLpeSatin,
+ ZigzagLineToSatin,
ConvertToStroke,
JumpToStroke,
FillToStroke,
diff --git a/lib/extensions/zigzag_line_to_satin.py b/lib/extensions/zigzag_line_to_satin.py
new file mode 100644
index 00000000..94a901c0
--- /dev/null
+++ b/lib/extensions/zigzag_line_to_satin.py
@@ -0,0 +1,145 @@
+# Authors: see git history
+#
+# Copyright (c) 2010 Authors
+# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
+
+import inkex
+
+from ..elements import Stroke
+from ..i18n import _
+from .base import InkstitchExtension
+
+
+class ZigzagLineToSatin(InkstitchExtension):
+ """Convert a satin column into a running stitch."""
+ def __init__(self, *args, **kwargs):
+ InkstitchExtension.__init__(self, *args, **kwargs)
+ self.arg_parser.add_argument("--zigzag_to_satin", type=str, default=None)
+ self.arg_parser.add_argument("--options", type=str, default=None)
+ self.arg_parser.add_argument("--info", type=str, default=None)
+
+ self.arg_parser.add_argument("-s", "--smoothing", type=inkex.Boolean, default=True, dest="smoothing")
+ self.arg_parser.add_argument("-p", "--pattern", type=str, default="square", dest="pattern")
+ self.arg_parser.add_argument("-r", "--rungs", type=inkex.Boolean, default=True, dest="rungs")
+ self.arg_parser.add_argument("-l", "--reduce-rungs", type=inkex.Boolean, default=False, dest="reduce_rungs")
+
+ def effect(self):
+ if not self.svg.selection or not self.get_elements():
+ inkex.errormsg(_("Please select at least one stroke."))
+ return
+
+ if not any(isinstance(item, Stroke) for item in self.elements):
+ # L10N: Convert To Satin extension, user selected one or more objects that were not lines.
+ inkex.errormsg(_("Please select at least one stroke to convert to a satin column."))
+ return
+
+ for element in self.elements:
+ d = []
+ point_list = list(element.node.get_path().end_points)
+ rails, rungs = self._get_rails_and_rungs(point_list)
+
+ if self.options.rungs:
+ if self.options.reduce_rungs and len(rungs) > 2:
+ rungs = rungs[0::2]
+ d.extend(self._rung_path(rungs))
+ if not self.options.smoothing:
+ for rail in rails:
+ d.append('M ' + ' '.join([str(point) for point in rail]))
+ else:
+ d.append(self._smooth_path(rails))
+
+ element.node.set('d', " ".join(d))
+ element.set_param('satin_column', True)
+ # remove dashes
+ element.update_dash(False)
+
+ def _get_rails_and_rungs(self, point_list):
+ if self.options.pattern == "sawtooth":
+ # sawtooth pattern: |/|/|/|
+ rails = [point_list[0::2], point_list[1::2]]
+ rungs = list(zip(point_list[1::2], point_list[:-1:2]))
+ return rails, rungs
+ elif self.options.pattern == "zigzag":
+ # zigzag pattern: VVVVV
+ rails = [point_list[0::2], point_list[1::2]]
+ rail_points = [[], []]
+ for i, rail in enumerate(rails):
+ for j, point in enumerate(rail):
+ if j == 0 or point in point_list[2::len(point_list)-3]:
+ rail_points[i].append(point)
+ continue
+ p0 = rail[j-1]
+ rail_points[i].append(inkex.DirectedLineSegment(p0, point).point_at_ratio(0.5))
+ rail_points[i].append(point)
+ rungs = list(zip(*rail_points))
+ return rail_points, rungs
+ else:
+ # square pattern: |_|▔|_|▔|
+ point_list = [point_list[i:i+4] for i in range(0, len(point_list), 4)]
+
+ rungs = []
+ rails = [[], []]
+ for i, points in enumerate(point_list):
+ if len(points) <= 1:
+ break
+
+ elif len(points) < 4 and len(points) > 1:
+ rails[0].append(points[0])
+ rails[1].append(points[1])
+ rungs.append([points[0], points[1]])
+ break
+
+ rails[0].extend([points[0], points[3]])
+ rails[1].extend([points[1], points[2]])
+ rungs.extend([[points[0], points[1]], [points[2], points[3]]])
+ return rails, rungs
+
+ def _smooth_path(self, rails):
+ path_commands = []
+ smoothing = 0.2
+ for rail in rails:
+ for i, point in enumerate(rail):
+ if i == 0:
+ path_commands.append(inkex.paths.Move(*point))
+ else:
+ # get the two previous points and the next point for handle calculation
+ if i < 2:
+ prev_prev = rail[i - 1]
+ else:
+ prev_prev = rail[i-2]
+ prev = rail[i-1]
+ if i > len(rail) - 2:
+ next = point
+ else:
+ next = rail[i+1]
+
+ # get length of handles
+ length = inkex.DirectedLineSegment(point, prev).length * smoothing
+
+ # get handle positions
+ start = inkex.DirectedLineSegment(prev_prev, point)
+ end = inkex.DirectedLineSegment(next, prev)
+ if not start.length == 0:
+ start = start.parallel(*prev).point_at_length(start.length - length)
+ else:
+ start = start.start
+ if not end.length == 0:
+ end = end.parallel(*point).point_at_length(end.length - length)
+ else:
+ end = end.start
+
+ # generate curves
+ path_commands.append(inkex.paths.Curve(*start, *end, *point))
+ return str(inkex.Path(path_commands))
+
+ def _rung_path(self, rungs):
+ if len(rungs) < 3:
+ return []
+ d = []
+ rungs = rungs[1:-1]
+ for point0, point1 in rungs:
+ line = inkex.DirectedLineSegment(point0, point1)
+ point0 = line.point_at_length(-0.3)
+ point1 = line.point_at_length(line.length + 0.3)
+ d.append(f'M {point0[0]}, {point0[1]} {point1[0]}, {point1[1]}')
+ return d
diff --git a/templates/zigzag_line_to_satin.xml b/templates/zigzag_line_to_satin.xml
new file mode 100644
index 00000000..b57baabb
--- /dev/null
+++ b/templates/zigzag_line_to_satin.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Zig-Zag Line to Satin</name>
+ <id>org.inkstitch.zigzag_line_to_satin</id>
+ <param name="extension" type="string" gui-hidden="true">zigzag_line_to_satin</param>
+ <param name="zigzag_to_satin" type="notebook">
+ <page name="options" gui-text="Options">
+ <label>Converts a zigzag line into a satin column.</label>
+ <param name="pattern" type="optiongroup" appearance="combo" gui-text="Line Pattern">
+ <option value="square">Square</option>
+ <option value="sawtooth">Sawtooth</option>
+ <option value="zigzag">Zigzag</option>
+ </param>
+ <param name="smoothing" type="boolean" gui-text="Smoothing">true</param>
+ <param name="rungs" type="boolean" gui-text="Add rungs">true</param>
+ <param indent="1" name="reduce-rungs" type="boolean" gui-text="Reduce number of rungs">false</param>
+ </page>
+ <page name="info" gui-text="Help">
+ <label appearance="header">This extension converts a zigzag line into a satin column.</label>
+ <spacer />
+ <label appearance="header">Line Pattern</label>
+ <label>▻ Always start and end with a rung.</label>
+ <spacer />
+ <label>Square: |_|▔|_|▔|</label>
+ <label>Sawtooth: |\|\|\|</label>
+ <label>Zigzag: |\/\/\/|</label>
+ <spacer />
+ <label>Get more information on our website</label>
+ <label appearance="url">https://inkstitch.org/docs/satin-tools/#zigzag-line-to-satin</label>
+ </page>
+ </param>
+ <effect>
+ <object-type>all</object-type>
+ <effects-menu>
+ <submenu name="Ink/Stitch" translatable="no">
+ <submenu name="Tools: Satin" />
+ </submenu>
+ </effects-menu>
+ </effect>
+ <script>
+ {{ command_tag | safe }}
+ </script>
+</inkscape-extension>