summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Neva <github.com@lexneva.name>2023-07-20 21:54:52 -0400
committerLex Neva <github.com@lexneva.name>2023-07-20 21:54:52 -0400
commit2957615bf237008851242781e28fb4c0259e557b (patch)
tree808808bef9e640e5a3bbf7d5e2911b6e844334c9
parentcf2a1d6a3b6e40e85b839b90c3e8d424c390cabd (diff)
add staggered and simple split satin
-rw-r--r--lib/elements/satin_column.py101
-rw-r--r--lib/svg/tags.py2
2 files changed, 80 insertions, 23 deletions
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
@@ -95,16 +95,6 @@ class SatinColumn(EmbroideryElement):
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'),
tooltip=_('shorten stitch across rails at most this percent. '
@@ -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)
diff --git a/lib/svg/tags.py b/lib/svg/tags.py
index 8045840d..b99073f1 100644
--- a/lib/svg/tags.py
+++ b/lib/svg/tags.py
@@ -148,6 +148,8 @@ inkstitch_attribs = [
'random_width_decrease_percent',
'random_width_increase_percent',
'random_zigzag_spacing_percent',
+ 'split_method',
+ 'split_staggers',
'random_split_phase',
'random_split_jitter_percent',
'min_random_split_length_mm',