From 7389980fae6856116ccf7419d92dcc29a0411851 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Tue, 18 Jul 2023 22:54:39 -0400 Subject: add S stitch --- lib/elements/satin_column.py | 59 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 86c6d05a..68974f13 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -81,7 +81,8 @@ class SatinColumn(EmbroideryElement): return self.get_boolean_param("satin_column") _satin_methods = [ParamOption('satin_column', _('Satin Column')), - ParamOption('e_stitch', _('"E" Stitch'))] + ParamOption('e_stitch', _('"E" Stitch')), + ParamOption('s_stitch', _('"S" Stitch'))] @property @param('satin_method', @@ -1136,15 +1137,13 @@ class SatinColumn(EmbroideryElement): # # _|_|_|_|_|_|_|_|_|_|_|_| - # print >> dbg, "satin", self.zigzag_spacing, self.pull_compensation - patch = StitchGroup(color=self.color) pairs = self.plot_points_on_rails( self.zigzag_spacing, self.pull_compensation_px, - self.pull_compensation_percent/100, - self.random_width_decrease.any() or self.random_width_increase.any() or self.random_zigzag_spacing, + self.pull_compensation_percent / 100, + True, ) short_pairs = self.inset_short_stitches_sawtooth(pairs) @@ -1182,6 +1181,54 @@ class SatinColumn(EmbroideryElement): patch.add_tags(("satin_column", "e_stitch")) return patch + def do_s_stitch(self): + # S stitch: do a pattern that looks like the letter "S". It looks like + # this: + # _ _ _ _ _ _ + # _| |_| |_| |_| |_| |_| | + + patch = StitchGroup(color=self.color) + + pairs = self.plot_points_on_rails( + self.zigzag_spacing, + self.pull_compensation_px, + self.pull_compensation_percent / 100, + True, + ) + + short_pairs = self.inset_short_stitches_sawtooth(pairs) + max_stitch_length = self.max_stitch_length_px + length_sigma = self.random_split_jitter + random_phase = self.random_split_phase + min_split_length = self.min_random_split_length_px + seed = self.random_seed + last_point = None + for i, (a, b), (a_short, b_short) in zip(itertools.count(0), pairs, short_pairs): + check_stop_flag() + points = [a_short] + split_points, _ = self.get_split_points( + a, b, a_short, b_short, max_stitch_length, + None, length_sigma, random_phase, min_split_length, + prng.join_args(seed, 'satin-split', 2 * i + 1)) + points.extend(split_points) + points.append(b_short) + + if i % 2 == 0: + points = list(reversed(points)) + + # zigzag spacing is wider than stitch length, subdivide + if last_point is not None and max_stitch_length is not None and self.zigzag_spacing > max_stitch_length: + initial_points, _ = self.get_split_points(last_point, points[0], last_point, points[0], max_stitch_length) + + patch.add_stitches(points) + last_point = points[-1] + + if self._center_walk_is_odd(): + patch.stitches = list(reversed(patch.stitches)) + + patch.add_tags(("satin", "s_stitch")) + return patch + def get_split_points(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, seed=None): if not length: return ([], None) @@ -1258,6 +1305,8 @@ class SatinColumn(EmbroideryElement): if self.satin_method == 'e_stitch': patch += self.do_e_stitch() + elif self.satin_method == 's_stitch': + patch += self.do_s_stitch() else: patch += self.do_satin() -- cgit v1.2.3 From 2957615bf237008851242781e28fb4c0259e557b Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Thu, 20 Jul 2023 21:54:52 -0400 Subject: add staggered and simple split satin --- lib/elements/satin_column.py | 101 +++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 23 deletions(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 68974f13..e9a4e32c 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -94,16 +94,6 @@ class SatinColumn(EmbroideryElement): def satin_method(self): return self.get_param('satin_method', 'satin_column') - @property - @param('max_stitch_length_mm', - _('Maximum stitch length'), - tooltip=_('Maximum stitch length for split stitches.'), - type='float', - unit="mm", - sort_index=1) - def max_stitch_length_px(self): - return self.get_float_param("max_stitch_length_mm") or None - @property @param('random_width_decrease_percent', _('Random percentage of satin width decrease'), @@ -133,18 +123,53 @@ class SatinColumn(EmbroideryElement): # peak-to-peak distance between zigzags return max(self.get_float_param("random_zigzag_spacing_percent", 0), 0) / 100 + _split_methods = [ParamOption('default', _('Default')), + ParamOption('simple', _('Simple')), + ParamOption('staggered', _('Staggered'))] + + @property + @param('split_method', + _('Split Method'), + type='combo', + default=0, + options=_split_methods, + sort_index=93) + def split_method(self): + return self.get_param('split_method', 'default') + + @property + @param('max_stitch_length_mm', + _('Maximum stitch length'), + tooltip=_('Maximum stitch length for split stitches.'), + type='float', + unit="mm", + sort_index=94) + def max_stitch_length_px(self): + return self.get_float_param("max_stitch_length_mm") or None + + @property + @param('random_split_jitter_percent', + _('Random jitter for split stitches'), + tooltip=_('Randomizes split stitch length if random phase is enabled, stitch position if disabled.'), + select_items=[('split_method', 'default')], + default=0, type='float', unit="± %", sort_index=95) + def random_split_jitter(self): + return min(max(self.get_float_param("random_split_jitter_percent", 0), 0), 100) / 100 + @property @param('random_split_phase', _('Random phase for split stitches'), tooltip=_('Controls whether split stitches are centered or with a random phase (which may increase stitch count).'), + select_items=[('split_method', 'default')], default=False, type='boolean', sort_index=96) def random_split_phase(self): return self.get_boolean_param('random_split_phase') @property @param('min_random_split_length_mm', - _('Minimum length for random-phase split.'), + _('Minimum length for random-phase split'), tooltip=_('Defaults to maximum stitch length. Smaller values allow for a transition between single-stitch and split-stitch.'), + select_items=[('split_method', 'default')], default='', type='float', unit='mm', sort_index=97) def min_random_split_length_px(self): if self.max_stitch_length_px is None: @@ -152,12 +177,16 @@ class SatinColumn(EmbroideryElement): return min(self.max_stitch_length_px, self.get_float_param('min_random_split_length_mm', self.max_stitch_length_px)) @property - @param('random_split_jitter_percent', - _('Random jitter for split stitches'), - tooltip=_('Randomizes split stitch length if random phase is enabled, stitch position if disabled.'), - default=0, type='float', unit="± %", sort_index=95) - def random_split_jitter(self): - return min(max(self.get_float_param("random_split_jitter_percent", 0), 0), 100) / 100 + @param('split_staggers', + _('Stagger split stitches this many times before repeating'), + # This tooltip is _exactly_ the same as the one for FillStitch.staggers, which + # means it will be translated the same. + tooltip=_('Length of the cycle by which successive stitch rows are staggered. ' + 'Fractional values are allowed and can have less visible diagonals than integer values.'), + select_items=[('split_method', 'staggered')], + default=4, type='float', sort_index=98) + def split_staggers(self): + return self.get_float_param('split_staggers', 4) @property @param('short_stitch_inset', @@ -1110,7 +1139,7 @@ class SatinColumn(EmbroideryElement): if last_point is not None: split_points, _ = self.get_split_points( last_point, a, last_short_point, a_short, max_stitch_length, last_count, - length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i)) + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), 2 * i) patch.add_stitches(split_points, ("satin_column", "satin_split_stitch")) patch.add_stitch(a_short) @@ -1118,7 +1147,7 @@ class SatinColumn(EmbroideryElement): split_points, last_count = self.get_split_points( a, b, a_short, b_short, max_stitch_length, None, - length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i + 1)) + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i + 1), 2 * i + 1) patch.add_stitches(split_points, ("satin_column", "satin_split_stitch")) patch.add_stitch(b_short) @@ -1160,7 +1189,7 @@ class SatinColumn(EmbroideryElement): split_points, _ = self.get_split_points( left, right, a_short, b_short, max_stitch_length, None, length_sigma, random_phase, min_split_length, - prng.join_args(seed, 'satin-split', 2 * i + 1)) + prng.join_args(seed, 'satin-split', 2 * i + 1), 2 * i + 1) # zigzag spacing is wider than stitch length, subdivide if last_point is not None and max_stitch_length is not None and self.zigzag_spacing > max_stitch_length: @@ -1209,7 +1238,7 @@ class SatinColumn(EmbroideryElement): split_points, _ = self.get_split_points( a, b, a_short, b_short, max_stitch_length, None, length_sigma, random_phase, min_split_length, - prng.join_args(seed, 'satin-split', 2 * i + 1)) + prng.join_args(seed, 'satin-split', i), i) points.extend(split_points) points.append(b_short) @@ -1229,7 +1258,16 @@ class SatinColumn(EmbroideryElement): patch.add_tags(("satin", "s_stitch")) return patch - def get_split_points(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, seed=None): + def get_split_points(self, *args, **kwargs): + if self.split_method == "default": + return self._get_split_points_default(*args, **kwargs) + elif self.split_method == "simple": + return self._get_split_points_simple(*args, **kwargs), None + elif self.split_method == "staggered": + return self._get_split_points_staggered(*args, **kwargs), None + + def _get_split_points_default(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, + seed=None, row_num=0): if not length: return ([], None) if min_split_length is None: @@ -1252,6 +1290,23 @@ class SatinColumn(EmbroideryElement): points = running_stitch.split_segment_even_dist(a, b, length, length_sigma, seed) return (points, len(points) + 1) + def _get_split_points_simple(self, *args, **kwargs): + return self._get_split_points_staggered(*args, **kwargs, _staggers=1) + + def _get_split_points_staggered(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, + seed=None, row_num=0, _staggers=None): + if not length: + return ([], None) + + if _staggers is None: + # This is only here to allow _get_split_points_simple to override + _staggers = self.split_staggers + + line = shgeo.LineString((a, b)) + a_short_projection = line.project(shgeo.Point(a_short)) + b_short_projection = line.project(shgeo.Point(b_short)) + return running_stitch.split_segment_stagger_phase(a, b, length, _staggers, row_num, min=a_short_projection, max=b_short_projection) + def inset_short_stitches_sawtooth(self, pairs): min_dist = self.short_stitch_distance inset = min(self.short_stitch_inset, 0.5) @@ -1266,7 +1321,7 @@ class SatinColumn(EmbroideryElement): continue dist = a.distance(b) inset_px = inset * dist - if max_stitch_length and not self.random_split_phase: + if self.split_method == "default" and max_stitch_length and not self.random_split_phase: # make sure inset is less than split etitch length inset_px = min(inset_px, max_stitch_length / 3) -- cgit v1.2.3 From b349f46a57409624da46dcc47aeccbf6322c59f1 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Thu, 20 Jul 2023 22:12:59 -0400 Subject: handle normal satin with stagger properly --- lib/elements/satin_column.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index e9a4e32c..7f3dff10 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1139,7 +1139,7 @@ class SatinColumn(EmbroideryElement): if last_point is not None: split_points, _ = self.get_split_points( last_point, a, last_short_point, a_short, max_stitch_length, last_count, - length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), 2 * i) + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), 2 * i, from_end=True) patch.add_stitches(split_points, ("satin_column", "satin_split_stitch")) patch.add_stitch(a_short) @@ -1267,7 +1267,7 @@ class SatinColumn(EmbroideryElement): return self._get_split_points_staggered(*args, **kwargs), None def _get_split_points_default(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, - seed=None, row_num=0): + seed=None, row_num=0, from_end=None): if not length: return ([], None) if min_split_length is None: @@ -1294,7 +1294,7 @@ class SatinColumn(EmbroideryElement): return self._get_split_points_staggered(*args, **kwargs, _staggers=1) def _get_split_points_staggered(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, - seed=None, row_num=0, _staggers=None): + seed=None, row_num=0, from_end=False, _staggers=None): if not length: return ([], None) @@ -1302,10 +1302,18 @@ class SatinColumn(EmbroideryElement): # This is only here to allow _get_split_points_simple to override _staggers = self.split_staggers + if from_end: + a, b = b, a + line = shgeo.LineString((a, b)) a_short_projection = line.project(shgeo.Point(a_short)) b_short_projection = line.project(shgeo.Point(b_short)) - return running_stitch.split_segment_stagger_phase(a, b, length, _staggers, row_num, min=a_short_projection, max=b_short_projection) + split_points = running_stitch.split_segment_stagger_phase(a, b, length, _staggers, row_num, min=a_short_projection, max=b_short_projection) + + if from_end: + split_points = list(reversed(split_points)) + + return split_points def inset_short_stitches_sawtooth(self, pairs): min_dist = self.short_stitch_distance -- cgit v1.2.3 From 6f8983c7e343550331e210665ec337d3e1902857 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Fri, 21 Jul 2023 22:36:55 -0400 Subject: fix from_end --- lib/elements/satin_column.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 7f3dff10..b0cd6716 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1304,6 +1304,7 @@ class SatinColumn(EmbroideryElement): if from_end: a, b = b, a + a_short, b_short = b_short, a_short line = shgeo.LineString((a, b)) a_short_projection = line.project(shgeo.Point(a_short)) -- cgit v1.2.3 From bd19cb93907ce977325b88c5586402d8ee67d4f3 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Fri, 21 Jul 2023 22:37:06 -0400 Subject: add zig-zag satin method --- lib/elements/satin_column.py | 46 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index b0cd6716..855d3134 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -82,7 +82,8 @@ class SatinColumn(EmbroideryElement): _satin_methods = [ParamOption('satin_column', _('Satin Column')), ParamOption('e_stitch', _('"E" Stitch')), - ParamOption('s_stitch', _('"S" Stitch'))] + ParamOption('s_stitch', _('"S" Stitch')), + ParamOption('zigzag', _('Zig-zag'))] @property @param('satin_method', @@ -1139,7 +1140,7 @@ class SatinColumn(EmbroideryElement): if last_point is not None: split_points, _ = self.get_split_points( last_point, a, last_short_point, a_short, max_stitch_length, last_count, - length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), 2 * i, from_end=True) + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), row_num=2 * i, from_end=True) patch.add_stitches(split_points, ("satin_column", "satin_split_stitch")) patch.add_stitch(a_short) @@ -1147,7 +1148,7 @@ class SatinColumn(EmbroideryElement): split_points, last_count = self.get_split_points( a, b, a_short, b_short, max_stitch_length, None, - length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i + 1), 2 * i + 1) + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i + 1), row_num=2 * i + 1) patch.add_stitches(split_points, ("satin_column", "satin_split_stitch")) patch.add_stitch(b_short) @@ -1258,6 +1259,43 @@ class SatinColumn(EmbroideryElement): patch.add_tags(("satin", "s_stitch")) return patch + def do_zigzag(self): + patch = StitchGroup(color=self.color) + + # calculate pairs at double the requested density + pairs = self.plot_points_on_rails( + self.zigzag_spacing / 2.0, + self.pull_compensation_px, + self.pull_compensation_percent / 100, + True, + ) + + # alternate picking one point from each pair, first on one rail then the other + points = [p[i % 2] for i, p in enumerate(pairs)] + + # turn the list of points back into pairs, (a, b), (b, c), (c, d), etc + pairs = list(zip(points[:-1], points[1:])) + + short_pairs = self.inset_short_stitches_sawtooth(pairs) + max_stitch_length = self.max_stitch_length_px + length_sigma = self.random_split_jitter + random_phase = self.random_split_phase + min_split_length = self.min_random_split_length_px + seed = self.random_seed + + patch.add_stitch(pairs[0][0]) + for i, (a, b), (a_short, b_short) in zip(itertools.count(0), pairs, short_pairs): + split_points, _ = self.get_split_points( + a, b, a_short, b_short, max_stitch_length, None, + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), row_num=i, from_end=(i % 2 == 0)) + patch.add_stitches(split_points, ("satin_column", "zigzag_split_stitch")) + patch.add_stitch(b) + + if self._center_walk_is_odd(): + patch.stitches = list(reversed(patch.stitches)) + + return patch + def get_split_points(self, *args, **kwargs): if self.split_method == "default": return self._get_split_points_default(*args, **kwargs) @@ -1371,6 +1409,8 @@ class SatinColumn(EmbroideryElement): patch += self.do_e_stitch() elif self.satin_method == 's_stitch': patch += self.do_s_stitch() + elif self.satin_method == 'zigzag': + patch += self.do_zigzag() else: patch += self.do_satin() -- cgit v1.2.3 From 1e4a63f5e6195ed606a050bf53e8aa8b72c347d9 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Fri, 21 Jul 2023 22:41:49 -0400 Subject: fix non-split case --- lib/elements/satin_column.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 855d3134..d137c2d6 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1334,7 +1334,7 @@ class SatinColumn(EmbroideryElement): def _get_split_points_staggered(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, seed=None, row_num=0, from_end=False, _staggers=None): if not length: - return ([], None) + return [] if _staggers is None: # This is only here to allow _get_split_points_simple to override -- cgit v1.2.3 From 6f541a79f302dca67fa5fc60ec3fd9659c7b7a85 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Fri, 21 Jul 2023 22:55:18 -0400 Subject: fix zig-zag short stitches --- lib/elements/satin_column.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index d137c2d6..25606ab8 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1273,8 +1273,8 @@ class SatinColumn(EmbroideryElement): # alternate picking one point from each pair, first on one rail then the other points = [p[i % 2] for i, p in enumerate(pairs)] - # turn the list of points back into pairs, (a, b), (b, c), (c, d), etc - pairs = list(zip(points[:-1], points[1:])) + # turn the list of points back into pairs + pairs = [points[i:i + 2] for i in range(0, len(points), 2)] short_pairs = self.inset_short_stitches_sawtooth(pairs) max_stitch_length = self.max_stitch_length_px @@ -1283,13 +1283,26 @@ class SatinColumn(EmbroideryElement): min_split_length = self.min_random_split_length_px seed = self.random_seed - patch.add_stitch(pairs[0][0]) + last_point = None + last_point_short = None for i, (a, b), (a_short, b_short) in zip(itertools.count(0), pairs, short_pairs): + if last_point: + split_points, _ = self.get_split_points( + last_point, a, last_point_short, a_short, max_stitch_length, None, + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), row_num=2 * i, from_end=True) + patch.add_stitches(split_points, ("satin_column", "zigzag_split_stitch")) + + patch.add_stitch(a_short) + split_points, _ = self.get_split_points( a, b, a_short, b_short, max_stitch_length, None, - length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i), row_num=i, from_end=(i % 2 == 0)) + length_sigma, random_phase, min_split_length, prng.join_args(seed, 'satin-split', 2 * i + 1), row_num=2 * i + 1) patch.add_stitches(split_points, ("satin_column", "zigzag_split_stitch")) - patch.add_stitch(b) + + patch.add_stitch(b_short) + + last_point = b + last_point_short = b_short if self._center_walk_is_odd(): patch.stitches = list(reversed(patch.stitches)) -- cgit v1.2.3 From 2358c6fa286e79707a656f66113e8796fa7ba063 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sun, 23 Jul 2023 10:53:55 -0400 Subject: avoid split if satin doesn't need it --- lib/elements/satin_column.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 25606ab8..ae96a1d7 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1346,7 +1346,7 @@ class SatinColumn(EmbroideryElement): def _get_split_points_staggered(self, a, b, a_short, b_short, length, count=None, length_sigma=0.0, random_phase=False, min_split_length=None, seed=None, row_num=0, from_end=False, _staggers=None): - if not length: + if not length or a.distance(b) <= length: return [] if _staggers is None: -- cgit v1.2.3 From c90064d0d3cf926bf54e0fbc1c70eaa9628757e4 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Thu, 7 Sep 2023 18:55:57 +0200 Subject: zigzag: ensure pairs --- lib/elements/satin_column.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/elements/satin_column.py') diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index ae96a1d7..25f50e13 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -1276,6 +1276,10 @@ class SatinColumn(EmbroideryElement): # turn the list of points back into pairs pairs = [points[i:i + 2] for i in range(0, len(points), 2)] + # remove last item if it isn't paired up + if len(pairs[-1]) == 1: + del pairs[-1] + short_pairs = self.inset_short_stitches_sawtooth(pairs) max_stitch_length = self.max_stitch_length_px length_sigma = self.random_split_jitter -- cgit v1.2.3