summaryrefslogtreecommitdiff
path: root/lib/elements
diff options
context:
space:
mode:
Diffstat (limited to 'lib/elements')
-rw-r--r--lib/elements/fill_stitch.py8
-rw-r--r--lib/elements/gradient_fill.py79
-rw-r--r--lib/elements/stroke.py37
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)