diff options
| -rw-r--r-- | lib/elements/satin_column.py | 66 | ||||
| -rw-r--r-- | lib/svg/tags.py | 2 | ||||
| -rw-r--r-- | lib/update.py | 5 |
3 files changed, 63 insertions, 10 deletions
diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 4f083b21..dafc9c6b 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -229,16 +229,61 @@ class SatinColumn(EmbroideryElement): # wider than we desire the column to end up. return self.get_split_mm_param_as_px("pull_compensation_mm", (0, 0)) + _reverse_rails_options = [ParamOption('automatic', _('Automatic')), + ParamOption('none', _("Don't reverse")), + ParamOption('first', _('Reverse first rail')), + ParamOption('second', _('Reverse second rail')), + ParamOption('both', _('Reverse both rails')) + ] + @property @param( - 'reverse_one_rail', - _('Reverse one rail'), - tooltip=_('Enabling this may help if your satin renders very strangely.'), - type='boolean', - default='false', + 'reverse_rails', + _('Reverse rails'), + tooltip=_('This may help if your satin renders very strangely. ' + + 'Default: automatically detect and fix a reversed rail.'), + type='combo', + options=_reverse_rails_options, + default='automatic', sort_index=10) - def reverse_one_rail(self): - return self.get_boolean_param('reverse_one_rail', False) + def reverse_rails(self): + return self.get_param('reverse_rails', 'automatic') + + def _get_rails_to_reverse(self, rails): + choice = self.reverse_rails + + if choice == 'first': + return True, False + elif choice == 'second': + return False, True + elif choice == 'both': + return True, True + elif choice == 'automatic': + if len(rails) == 2: + # Sample ten points along the rails. Compare the distance + # between corresponding points on both rails with and without + # one rail reversed. If the average distance between points + # with one rail reversed is less than without one reversed, then + # the user has probably accidentally reversed a rail. + lengths = [] + lengths_reverse = [] + + for i in range(10): + distance = i / 10 + point0 = rails[0].interpolate(distance, normalized=True) + point1 = rails[1].interpolate(distance, normalized=True) + point1_reverse = rails[1].interpolate(1 - distance, normalized=True) + + lengths.append(point0.distance(point1)) + lengths_reverse.append(point0.distance(point1_reverse)) + + debug.log(f"lengths: {lengths}") + debug.log(f"lengths_reverse: {lengths_reverse}") + if sum(lengths) > sum(lengths_reverse): + # reverse the second rail + return False, True + + return None @property @param( @@ -416,8 +461,11 @@ class SatinColumn(EmbroideryElement): """The rails, as LineStrings.""" paths = [shgeo.LineString(self.flatten_subpath(rail)) for rail in self.rails] - if paths and self.reverse_one_rail: - paths[0] = shgeo.LineString(paths[0].coords[::-1]) + rails_to_reverse = self._get_rails_to_reverse(paths) + if paths and rails_to_reverse is not None: + for i, reverse in enumerate(rails_to_reverse): + if reverse: + paths[i] = shgeo.LineString(paths[i].coords[::-1]) return tuple(paths) diff --git a/lib/svg/tags.py b/lib/svg/tags.py index 8ce0c8a2..ba8bf558 100644 --- a/lib/svg/tags.py +++ b/lib/svg/tags.py @@ -124,7 +124,7 @@ inkstitch_attribs = [ 'short_stitch_distance_mm', 'short_stitch_inset', 'running_stitch_length_mm', - 'reverse_one_rail', + 'reverse_rails', 'swap_satin_rails', 'center_walk_underlay', 'center_walk_underlay_stitch_length_mm', diff --git a/lib/update.py b/lib/update.py index cba6f671..5f458d23 100644 --- a/lib/update.py +++ b/lib/update.py @@ -116,6 +116,11 @@ def _update_to_one(element): # noqa: C901 not element.node.style('stroke-dasharray')): element.set_param('stroke_method', 'zigzag_stitch') + if element.get_boolean_param('satin_column', False): + # reverse_rails defaults to Automatic, but we should never reverse an + # old satin automatically, only new ones + element.set_param('reverse_rails', 'none') + def _replace_legacy_embroider_param(element, param): # remove "embroider_" prefix |
