diff options
Diffstat (limited to 'lib/elements')
| -rw-r--r-- | lib/elements/fill_stitch.py | 8 | ||||
| -rw-r--r-- | lib/elements/gradient_fill.py | 79 | ||||
| -rw-r--r-- | lib/elements/stroke.py | 37 |
3 files changed, 33 insertions, 91 deletions
diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 912f3ba6..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', @@ -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<message>.+)\[(?P<x>.+)\s(?P<y>.+)\]", 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<message>.+)\[(?P<x>.+)\s(?P<y>.+)\]", why).groups() if "Hole lies outside shell" in message: yield UnconnectedWarning((x, y)) else: 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/elements/stroke.py b/lib/elements/stroke.py index 16689901..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', @@ -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) |
