add staggered and simple split satin

pull/2431/head
Lex Neva 2023-07-20 21:54:52 -04:00
rodzic cf2a1d6a3b
commit 2957615bf2
2 zmienionych plików z 80 dodań i 23 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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',