From 65272ec7ca75bc232da1da316bf69b91c9018a1c Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 10 May 2023 09:25:44 +0200 Subject: stroke to satin: avoid topology error --- lib/extensions/convert_to_satin.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/extensions/convert_to_satin.py b/lib/extensions/convert_to_satin.py index 5512a095..7a36ce21 100644 --- a/lib/extensions/convert_to_satin.py +++ b/lib/extensions/convert_to_satin.py @@ -99,6 +99,7 @@ class ConvertToSatin(InkstitchExtension): path[0] = start.as_tuple() def remove_duplicate_points(self, path): + path = [[round(coord, 4) for coord in point] for point in path] return [point for point, repeats in groupby(path)] def join_style_args(self, element): -- cgit v1.2.3 From 39627371acc4c5e6081ec1b22552d063e28ff670 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 10 May 2023 15:37:31 +0200 Subject: update comment --- lib/extensions/update_svg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/extensions/update_svg.py b/lib/extensions/update_svg.py index 51960cb2..0f0609be 100644 --- a/lib/extensions/update_svg.py +++ b/lib/extensions/update_svg.py @@ -14,8 +14,8 @@ class UpdateSvg(InkstitchExtension): def __init__(self, *args, **kwargs): InkstitchExtension.__init__(self, *args, **kwargs) - # TODO: When there are more legacy versions than only one, this can be transformed in a user input - # inkstitch_svg_version history: 1 -> v2.3.0 + # TODO: When there are more legacy versions than only one, this can be transformed into a user input + # inkstitch_svg_version history: 1 -> v3.0.0, May 2023 self.update_from = 0 def effect(self): -- cgit v1.2.3 From 573abab9e7fde4c863ee37a5b7e7d5fbcc540c34 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 10 May 2023 15:57:21 +0200 Subject: add help tab to gradient block extension --- lib/extensions/gradient_blocks.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/extensions/gradient_blocks.py b/lib/extensions/gradient_blocks.py index 563e3127..d80d5340 100644 --- a/lib/extensions/gradient_blocks.py +++ b/lib/extensions/gradient_blocks.py @@ -28,6 +28,9 @@ class GradientBlocks(CommandsExtension): def __init__(self, *args, **kwargs): CommandsExtension.__init__(self, *args, **kwargs) + self.arg_parser.add_argument("--notebook", type=str, default=0.0) + self.arg_parser.add_argument("--options", type=str, default=0.0) + self.arg_parser.add_argument("--info", type=str, default=0.0) self.arg_parser.add_argument("-e", "--end-row-spacing", type=float, default=0.0, dest="end_row_spacing") def effect(self): -- cgit v1.2.3 From 0f78733c4b2da2dbb138452f63759f6d3272d56a Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 10 May 2023 16:35:37 +0200 Subject: fix macos issue with no custom font dir --- lib/lettering/font.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/lettering/font.py b/lib/lettering/font.py index f5517797..c4c16729 100644 --- a/lib/lettering/font.py +++ b/lib/lettering/font.py @@ -182,6 +182,9 @@ class Font(object): return self.name + '*' def is_custom_font(self): + custom_dir = get_custom_font_dir() + if not custom_dir: + return False return get_custom_font_dir() in self.path def render_text(self, text, destination_group, variant=None, back_and_forth=True, trim_option=0, use_trim_symbols=False): -- cgit v1.2.3 From 3574f0e17958b83b07854b7ee857aee06f38d5a8 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 10 May 2023 17:12:20 +0200 Subject: do it right --- lib/lettering/font.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/lettering/font.py b/lib/lettering/font.py index c4c16729..77f17e7f 100644 --- a/lib/lettering/font.py +++ b/lib/lettering/font.py @@ -185,7 +185,7 @@ class Font(object): custom_dir = get_custom_font_dir() if not custom_dir: return False - return get_custom_font_dir() in self.path + return custom_dir in self.path def render_text(self, text, destination_group, variant=None, back_and_forth=True, trim_option=0, use_trim_symbols=False): -- cgit v1.2.3 From 3a441427da441e1c13c349453ae642de9fdc7ab2 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sat, 13 May 2023 12:24:48 +0200 Subject: ripple constant end position --- lib/stitches/ripple_stitch.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py index 4e1c563e..dc85445a 100644 --- a/lib/stitches/ripple_stitch.py +++ b/lib/stitches/ripple_stitch.py @@ -103,6 +103,11 @@ def _get_satin_line_count(stroke, pairs): if shortest_line_len == 0 or length < shortest_line_len: shortest_line_len = length num_lines = ceil(shortest_line_len / stroke.min_line_dist) + # we want the line count to be constantly even or odd (even if the design is resized + # so the stitch plan can be carefully planed connecting the end point to the following object + if stroke.line_count % 2 != num_lines % 2: + num_lines -= 1 + # for flat join styles we need to add an other line if stroke.join_style == 1: num_lines += 1 return num_lines -- cgit v1.2.3 From 111fd8f0ef7bc8e62322c38a7a7467c453f85331 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sat, 13 May 2023 21:11:27 +0200 Subject: * move all gradient methods to extension * add underlay to single color elements to compensate density --- lib/elements/gradient_fill.py | 79 --------------------------- lib/extensions/gradient_blocks.py | 110 +++++++++++++++++++++++++++++++++----- lib/stitches/ripple_stitch.py | 5 +- 3 files changed, 99 insertions(+), 95 deletions(-) delete mode 100644 lib/elements/gradient_fill.py (limited to 'lib') diff --git a/lib/elements/gradient_fill.py b/lib/elements/gradient_fill.py deleted file mode 100644 index 18443368..00000000 --- a/lib/elements/gradient_fill.py +++ /dev/null @@ -1,79 +0,0 @@ -from math import pi - -from inkex import DirectedLineSegment, Transform -from shapely import geometry as shgeo -from shapely.affinity import affine_transform, rotate -from shapely.ops import split - -from ..svg import PIXELS_PER_MM, get_correction_transform - - -def gradient_shapes_and_attributes(element, shape): - # e.g. url(#linearGradient872) -> linearGradient872 - color = element.color[5:-1] - xpath = f'.//svg:defs/svg:linearGradient[@id="{color}"]' - gradient = element.node.getroottree().getroot().findone(xpath) - gradient.apply_transform() - point1 = (float(gradient.get('x1')), float(gradient.get('y1'))) - point2 = (float(gradient.get('x2')), float(gradient.get('y2'))) - # get 90° angle to calculate the splitting angle - line = DirectedLineSegment(point1, point2) - angle = line.angle - (pi / 2) - # Ink/Stitch somehow turns the stitch angle - stitch_angle = angle * -1 - # create bbox polygon to calculate the length necessary to make sure that - # the gradient splitter lines will cut the entire design - bbox = element.node.bounding_box() - bbox_polygon = shgeo.Polygon([(bbox.left, bbox.top), (bbox.right, bbox.top), - (bbox.right, bbox.bottom), (bbox.left, bbox.bottom)]) - # gradient stops - offsets = gradient.stop_offsets - stop_styles = gradient.stop_styles - # now split the shape according to the gradient stops - polygons = [] - colors = [] - attributes = [] - previous_color = None - end_row_spacing = None - for i, offset in enumerate(offsets): - shape_rest = [] - split_point = shgeo.Point(line.point_at_ratio(float(offset))) - length = split_point.hausdorff_distance(bbox_polygon) - split_line = shgeo.LineString([(split_point.x - length - 2, split_point.y), - (split_point.x + length + 2, split_point.y)]) - split_line = rotate(split_line, angle, origin=split_point, use_radians=True) - transform = -Transform(get_correction_transform(element.node)) - transform = list(transform.to_hexad()) - split_line = affine_transform(split_line, transform) - offset_line = split_line.parallel_offset(1, 'right') - polygon = split(shape, split_line) - color = stop_styles[i]['stop-color'] - # does this gradient line split the shape - offset_outside_shape = len(polygon.geoms) == 1 - for poly in polygon.geoms: - if isinstance(poly, shgeo.Polygon) and element.shape_is_valid(poly): - if poly.intersects(offset_line): - if previous_color: - polygons.append(poly) - colors.append(previous_color) - attributes.append({'angle': stitch_angle, 'end_row_spacing': end_row_spacing, 'color': previous_color}) - polygons.append(poly) - attributes.append({'angle': stitch_angle + pi, 'end_row_spacing': end_row_spacing, 'color': color}) - else: - shape_rest.append(poly) - shape = shgeo.MultiPolygon(shape_rest) - previous_color = color - end_row_spacing = element.row_spacing / PIXELS_PER_MM * 2 - # add left over shape(s) - if shape: - if offset_outside_shape: - for s in shape.geoms: - polygons.append(s) - attributes.append({'color': stop_styles[-2]['stop-color'], 'angle': stitch_angle, 'end_row_spacing': end_row_spacing}) - stitch_angle += pi - else: - end_row_spacing = None - for s in shape.geoms: - polygons.append(s) - attributes.append({'color': stop_styles[-1]['stop-color'], 'angle': stitch_angle, 'end_row_spacing': end_row_spacing}) - return polygons, attributes diff --git a/lib/extensions/gradient_blocks.py b/lib/extensions/gradient_blocks.py index d80d5340..5d8318b6 100644 --- a/lib/extensions/gradient_blocks.py +++ b/lib/extensions/gradient_blocks.py @@ -3,17 +3,18 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from math import degrees +from math import degrees, pi -from inkex import DirectedLineSegment, PathElement, errormsg +from inkex import DirectedLineSegment, PathElement, Transform, errormsg +from shapely import geometry as shgeo +from shapely.affinity import affine_transform, rotate from shapely.geometry import Point -from shapely.ops import nearest_points +from shapely.ops import nearest_points, split from ..commands import add_commands from ..elements import FillStitch -from ..elements.gradient_fill import gradient_shapes_and_attributes from ..i18n import _ -from ..svg import get_correction_transform +from ..svg import PIXELS_PER_MM, get_correction_transform from ..svg.tags import INKSTITCH_ATTRIBS from .commands import CommandsExtension from .duplicate_params import get_inkstitch_attributes @@ -56,35 +57,45 @@ class GradientBlocks(CommandsExtension): fill_shapes.reverse() attributes.reverse() + if self.options.end_row_spacing != 0: + end_row_spacing = self.options.end_row_spacing + else: + end_row_spacing = element.row_spacing / PIXELS_PER_MM * 2 + end_row_spacing = f'{end_row_spacing: .2f}' + previous_color = None previous_element = None for i, shape in enumerate(fill_shapes): color = attributes[i]['color'] style['fill'] = color - end_row_spacing = attributes[i]['end_row_spacing'] or None + is_gradient = attributes[i]['is_gradient'] angle = degrees(attributes[i]['angle']) + angle = f'{angle: .2f}' d = "M " + " ".join([f'{x}, {y}' for x, y in list(shape.exterior.coords)]) + " Z" block = PathElement(attrib={ "id": self.uniqueId("path"), "style": str(style), "transform": correction_transform, "d": d, - INKSTITCH_ATTRIBS['angle']: f'{angle: .2f}' + INKSTITCH_ATTRIBS['angle']: angle }) # apply parameters from original element params = get_inkstitch_attributes(element.node) for attrib in params: block.attrib[attrib] = str(element.node.attrib[attrib]) - # set end_row_spacing - if end_row_spacing: - if self.options.end_row_spacing != 0: - end_row_spacing = self.options.end_row_spacing - block.set('inkstitch:end_row_spacing_mm', f'{end_row_spacing: .2f}') - else: - block.pop('inkstitch:end_row_spacing_mm') # disable underlay and underpath block.set('inkstitch:fill_underlay', False) block.set('inkstitch:underpath', False) + # set end_row_spacing + if is_gradient: + block.set('inkstitch:end_row_spacing_mm', end_row_spacing) + else: + block.pop('inkstitch:end_row_spacing_mm') + # use underlay to compensate for higher density in the gradient parts + block.set('inkstitch:fill_underlay', True) + block.set('inkstitch:fill_underlay_angle', angle) + block.set('inkstitch:fill_underlay_row_spacing_mm', end_row_spacing) + parent.insert(index, block) if previous_color == color: @@ -109,6 +120,77 @@ class GradientBlocks(CommandsExtension): return Point(pos) +def gradient_shapes_and_attributes(element, shape): + # e.g. url(#linearGradient872) -> linearGradient872 + color = element.color[5:-1] + xpath = f'.//svg:defs/svg:linearGradient[@id="{color}"]' + gradient = element.node.getroottree().getroot().findone(xpath) + gradient.apply_transform() + point1 = (float(gradient.get('x1')), float(gradient.get('y1'))) + point2 = (float(gradient.get('x2')), float(gradient.get('y2'))) + # get 90° angle to calculate the splitting angle + line = DirectedLineSegment(point1, point2) + angle = line.angle - (pi / 2) + # Ink/Stitch somehow turns the stitch angle + stitch_angle = angle * -1 + # create bbox polygon to calculate the length necessary to make sure that + # the gradient splitter lines will cut the entire design + bbox = element.node.bounding_box() + bbox_polygon = shgeo.Polygon([(bbox.left, bbox.top), (bbox.right, bbox.top), + (bbox.right, bbox.bottom), (bbox.left, bbox.bottom)]) + # gradient stops + offsets = gradient.stop_offsets + stop_styles = gradient.stop_styles + # now split the shape according to the gradient stops + polygons = [] + colors = [] + attributes = [] + previous_color = None + is_gradient = False + for i, offset in enumerate(offsets): + shape_rest = [] + split_point = shgeo.Point(line.point_at_ratio(float(offset))) + length = split_point.hausdorff_distance(bbox_polygon) + split_line = shgeo.LineString([(split_point.x - length - 2, split_point.y), + (split_point.x + length + 2, split_point.y)]) + split_line = rotate(split_line, angle, origin=split_point, use_radians=True) + transform = -Transform(get_correction_transform(element.node)) + transform = list(transform.to_hexad()) + split_line = affine_transform(split_line, transform) + offset_line = split_line.parallel_offset(1, 'right') + polygon = split(shape, split_line) + color = stop_styles[i]['stop-color'] + # does this gradient line split the shape + offset_outside_shape = len(polygon.geoms) == 1 + for poly in polygon.geoms: + if isinstance(poly, shgeo.Polygon) and element.shape_is_valid(poly): + if poly.intersects(offset_line): + if previous_color: + polygons.append(poly) + colors.append(previous_color) + attributes.append({'color': previous_color, 'angle': stitch_angle, 'is_gradient': is_gradient}) + polygons.append(poly) + attributes.append({'color': color, 'angle': stitch_angle + pi, 'is_gradient': is_gradient}) + else: + shape_rest.append(poly) + shape = shgeo.MultiPolygon(shape_rest) + previous_color = color + is_gradient = True + # add left over shape(s) + if shape: + if offset_outside_shape: + for s in shape.geoms: + polygons.append(s) + attributes.append({'color': stop_styles[-2]['stop-color'], 'angle': stitch_angle, 'is_gradient': is_gradient}) + stitch_angle += pi + else: + is_gradient = False + for s in shape.geoms: + polygons.append(s) + attributes.append({'color': stop_styles[-1]['stop-color'], 'angle': stitch_angle, 'is_gradient': is_gradient}) + return polygons, attributes + + if __name__ == '__main__': e = GradientBlocks() e.effect() diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py index dc85445a..52d91c2d 100644 --- a/lib/stitches/ripple_stitch.py +++ b/lib/stitches/ripple_stitch.py @@ -103,8 +103,9 @@ def _get_satin_line_count(stroke, pairs): if shortest_line_len == 0 or length < shortest_line_len: shortest_line_len = length num_lines = ceil(shortest_line_len / stroke.min_line_dist) - # we want the line count to be constantly even or odd (even if the design is resized - # so the stitch plan can be carefully planed connecting the end point to the following object + # We want the line count always to be either even or odd - depending on the line count value. + # So that the end point stays the same even if the design is resized. This is necessary to enable + # the user to carefully plan the output and and connect the end point to the following object if stroke.line_count % 2 != num_lines % 2: num_lines -= 1 # for flat join styles we need to add an other line -- cgit v1.2.3 From 6931d4868d05128b4bb148fe1714dedc808591b4 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 14 May 2023 09:11:33 +0200 Subject: ripple: line count --- lib/stitches/ripple_stitch.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py index 52d91c2d..80800b04 100644 --- a/lib/stitches/ripple_stitch.py +++ b/lib/stitches/ripple_stitch.py @@ -103,15 +103,7 @@ def _get_satin_line_count(stroke, pairs): if shortest_line_len == 0 or length < shortest_line_len: shortest_line_len = length num_lines = ceil(shortest_line_len / stroke.min_line_dist) - # We want the line count always to be either even or odd - depending on the line count value. - # So that the end point stays the same even if the design is resized. This is necessary to enable - # the user to carefully plan the output and and connect the end point to the following object - if stroke.line_count % 2 != num_lines % 2: - num_lines -= 1 - # for flat join styles we need to add an other line - if stroke.join_style == 1: - num_lines += 1 - return num_lines + return _line_count_adjust(stroke, num_lines) def _get_target_line_count(stroke, target, outline): @@ -123,9 +115,19 @@ def _get_guided_line_count(stroke, guide_line): num_lines = stroke.line_count else: num_lines = ceil(guide_line.length / stroke.min_line_dist) + return _line_count_adjust(stroke, num_lines) + + +def _line_count_adjust(stroke, num_lines): + if stroke.min_line_dist and stroke.line_count % 2 != num_lines % 2: + # We want the line count always to be either even or odd - depending on the line count value. + # So that the end point stays the same even if the design is resized. This is necessary to enable + # the user to carefully plan the output and and connect the end point to the following object + num_lines -= 1 if stroke.is_closed or stroke.join_style == 1: + # for flat join styles we need to add an other line num_lines += 1 - return num_lines + return max(1, num_lines) def _get_helper_lines(stroke): -- cgit v1.2.3 From 6c46eb2d866f97a1009a20a4446dbc3bdfcbb98a Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 14 May 2023 09:32:23 +0200 Subject: ripple: ensure min line count --- lib/stitches/ripple_stitch.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py index 80800b04..40a522eb 100644 --- a/lib/stitches/ripple_stitch.py +++ b/lib/stitches/ripple_stitch.py @@ -124,10 +124,12 @@ def _line_count_adjust(stroke, num_lines): # So that the end point stays the same even if the design is resized. This is necessary to enable # the user to carefully plan the output and and connect the end point to the following object num_lines -= 1 + # ensure minimum line count + num_lines = max(1, num_lines) if stroke.is_closed or stroke.join_style == 1: # for flat join styles we need to add an other line num_lines += 1 - return max(1, num_lines) + return num_lines def _get_helper_lines(stroke): -- cgit v1.2.3 From e8a6516471a1f105eb8bcab266bc8fe37e27fee9 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 14 May 2023 20:56:17 +0200 Subject: add reverse rails to ripple --- lib/elements/stroke.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 16689901..db044a2c 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -261,6 +261,27 @@ class Stroke(EmbroideryElement): def reverse(self): return self.get_boolean_param("reverse", False) + _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_rails', + _('Reverse rails'), + tooltip=_('Reverse satin ripple rails. ' + + 'Default: automatically detect and fix a reversed rail.'), + type='combo', + options=_reverse_rails_options, + default='automatic', + select_items=[('stroke_method', 'ripple_stitch')], + sort_index=15) + def reverse_rails(self): + return self.get_param('reverse_rails', 'automatic') + @property @param('grid_size_mm', _('Grid size'), @@ -269,7 +290,7 @@ class Stroke(EmbroideryElement): default=0, unit='mm', select_items=[('stroke_method', 'ripple_stitch')], - sort_index=15) + sort_index=16) @cache def grid_size(self): return abs(self.get_float_param("grid_size_mm", 0)) @@ -283,7 +304,7 @@ class Stroke(EmbroideryElement): # 0: xy, 1: x, 2: y, 3: none options=["X Y", "X", "Y", _("None")], select_items=[('stroke_method', 'ripple_stitch')], - sort_index=16) + sort_index=17) def scale_axis(self): return self.get_int_param('scale_axis', 0) @@ -295,7 +316,7 @@ class Stroke(EmbroideryElement): unit='%', default=100, select_items=[('stroke_method', 'ripple_stitch')], - sort_index=17) + sort_index=18) def scale_start(self): return self.get_float_param('scale_start', 100.0) @@ -307,7 +328,7 @@ class Stroke(EmbroideryElement): unit='%', default=0.0, select_items=[('stroke_method', 'ripple_stitch')], - sort_index=18) + sort_index=19) def scale_end(self): return self.get_float_param('scale_end', 0.0) @@ -318,7 +339,7 @@ class Stroke(EmbroideryElement): type='boolean', default=True, select_items=[('stroke_method', 'ripple_stitch')], - sort_index=19) + sort_index=20) @cache def rotate_ripples(self): return self.get_boolean_param("rotate_ripples", True) @@ -331,7 +352,7 @@ class Stroke(EmbroideryElement): default=0, options=(_("flat"), _("point")), select_items=[('stroke_method', 'ripple_stitch')], - sort_index=20) + sort_index=21) @cache def join_style(self): return self.get_int_param('join_style', 0) -- cgit v1.2.3 From d655aa1e1f0a9d4c655698f6db852e3f6947f5d2 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Mon, 15 May 2023 19:19:44 +0200 Subject: troubleshoot: read numbers with exponent --- lib/elements/fill_stitch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 912f3ba6..62bd1aca 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -607,13 +607,13 @@ class FillStitch(EmbroideryElement): def validation_errors(self): if not self.shape_is_valid(self.shape): why = explain_validity(self.shape) - message, x, y = re.findall(r".+?(?=\[)|-?\d+(?:\.\d+)?", why) + message, x, y = re.match(r"(?P.+)\[(?P.+)\s(?P.+)\]", why).groups() yield InvalidShapeError((x, y)) def validation_warnings(self): # noqa: C901 if not self.shape_is_valid(self.original_shape): why = explain_validity(self.original_shape) - message, x, y = re.findall(r".+?(?=\[)|-?\d+(?:\.\d+)?", why) + message, x, y = re.match(r"(?P.+)\[(?P.+)\s(?P.+)\]", why).groups() if "Hole lies outside shell" in message: yield UnconnectedWarning((x, y)) else: -- cgit v1.2.3 From a300fa32fc729f6cd7fb15f0dbb0da79ee36417e Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Mon, 15 May 2023 22:26:31 +0200 Subject: legacy satin ripple: do not reverse rails automatically --- lib/update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/update.py b/lib/update.py index 6287a77c..126f8ec1 100644 --- a/lib/update.py +++ b/lib/update.py @@ -104,7 +104,7 @@ def _update_to_one(element): # noqa: C901 element.remove_param('e_stitch') element.set_param('satin_method', 'e_stitch') - if element.get_boolean_param('satin_column', False): + if element.get_boolean_param('satin_column', False) or element.get_int_param('stroke_method', 0) == 1: # reverse_rails defaults to Automatic, but we should never reverse an # old satin automatically, only new ones element.set_param('reverse_rails', 'none') -- cgit v1.2.3 From a7e1de5c67c660cf8963b73358e08634ba8b3c39 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 16 May 2023 16:26:57 +0200 Subject: lpe satin: warn about empty d-attribute --- lib/extensions/stroke_to_lpe_satin.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/extensions/stroke_to_lpe_satin.py b/lib/extensions/stroke_to_lpe_satin.py index 5aa873e9..b89e471c 100644 --- a/lib/extensions/stroke_to_lpe_satin.py +++ b/lib/extensions/stroke_to_lpe_satin.py @@ -5,7 +5,7 @@ import inkex -from ..elements import SatinColumn, Stroke +from ..elements import EmptyDObject, SatinColumn, Stroke from ..i18n import _ from ..svg.tags import ORIGINAL_D, PATH_EFFECT, SODIPODI_NODETYPES from .base import InkstitchExtension @@ -35,7 +35,10 @@ class StrokeToLpeSatin(InkstitchExtension): if not any((isinstance(item, Stroke) or isinstance(item, SatinColumn)) 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.")) + if any(isinstance(item, EmptyDObject) for item in self.elements): + inkex.errormsg(_("This element has lost its path information. Please move the element slightly back and forth before you try again.")) + else: + inkex.errormsg(_("Please select at least one stroke to convert to a satin column.")) return pattern = self.options.pattern -- cgit v1.2.3 From 66068208e87f5464fa6b8038b74fe95de6b21bb9 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Tue, 16 May 2023 16:27:52 +0200 Subject: change running stitch length default --- lib/elements/fill_stitch.py | 4 ++-- lib/elements/stroke.py | 4 ++-- lib/update.py | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 62bd1aca..91cad563 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -352,14 +352,14 @@ class FillStitch(EmbroideryElement): 'Also used for meander and circular fill.'), unit='mm', type='float', - default=1.5, + default=2.5, select_items=[('fill_method', 'auto_fill'), ('fill_method', 'guided_fill'), ('fill_method', 'meander_fill'), ('fill_method', 'circular_fill')], sort_index=31) def running_stitch_length(self): - return max(self.get_float_param("running_stitch_length_mm", 1.5), 0.01) + return max(self.get_float_param("running_stitch_length_mm", 2.5), 0.01) @property @param('running_stitch_tolerance_mm', diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index db044a2c..ac54908b 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -101,10 +101,10 @@ class Stroke(EmbroideryElement): unit='mm', type='float', select_items=[('stroke_method', 'running_stitch'), ('stroke_method', 'ripple_stitch')], - default=1.5, + default=2.5, sort_index=4) def running_stitch_length(self): - return max(self.get_float_param("running_stitch_length_mm", 1.5), 0.01) + return max(self.get_float_param("running_stitch_length_mm", 2.5), 0.01) @property @param('running_stitch_tolerance_mm', diff --git a/lib/update.py b/lib/update.py index 126f8ec1..b0bfcdfa 100644 --- a/lib/update.py +++ b/lib/update.py @@ -112,6 +112,9 @@ def _update_to_one(element): # noqa: C901 # default setting for fill_underlay has changed if legacy_attribs and not element.get_param('fill_underlay', ""): element.set_param('fill_underlay', False) + # default setting for running stitch length has changed (fills and strokes, not satins) + if not element.get_boolean_param('satin_column', False) and element.get_float_param('running_stitch_length_mm', None) is None: + element.set_param('running_stitch_length_mm', 1.5) # convert legacy stroke_method if element.get_style("stroke") and not element.node.get('inkscape:connection-start', None): -- cgit v1.2.3