summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/commands.py8
-rw-r--r--lib/elements/fill_stitch.py3
-rw-r--r--lib/elements/satin_column.py16
-rw-r--r--lib/extensions/zigzag_line_to_satin.py91
-rw-r--r--lib/stitches/ripple_stitch.py11
5 files changed, 96 insertions, 33 deletions
diff --git a/lib/commands.py b/lib/commands.py
index 1214e9bc..bd4bd6d5 100644
--- a/lib/commands.py
+++ b/lib/commands.py
@@ -400,9 +400,11 @@ def add_commands(element, commands, pos=None):
remove_legacy_param(element, command)
group = add_group(svg, element.node, command)
- if pos is None:
- pos = get_command_pos(element, i, len(commands))
- symbol = add_symbol(svg, group, command, pos)
+ position = pos
+ if position is None:
+ position = get_command_pos(element, i, len(commands))
+
+ symbol = add_symbol(svg, group, command, position)
add_connector(svg, symbol, command, element)
diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py
index 91cad563..80e68247 100644
--- a/lib/elements/fill_stitch.py
+++ b/lib/elements/fill_stitch.py
@@ -769,8 +769,7 @@ class FillStitch(EmbroideryElement):
starting_point,
underpath=self.underlay_underpath))
stitch_groups.append(underlay)
-
- starting_point = underlay.stitches[-1]
+ starting_point = underlay.stitches[-1]
return [stitch_groups, starting_point]
def do_auto_fill(self, shape, last_patch, starting_point, ending_point):
diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py
index 0cc33203..f9fdd8bc 100644
--- a/lib/elements/satin_column.py
+++ b/lib/elements/satin_column.py
@@ -108,7 +108,7 @@ class SatinColumn(EmbroideryElement):
_('Random percentage of satin width decrease'),
tooltip=_('shorten stitch across rails at most this percent. '
'Two values separated by a space may be used for an aysmmetric effect.'),
- default=0, type='float', unit="% (each side)", sort_index=91)
+ default=0, type='float', unit=_("% (each side)"), sort_index=91)
@cache
def random_width_decrease(self):
return self.get_split_float_param("random_width_decrease_percent", (0, 0)) / 100
@@ -118,7 +118,7 @@ class SatinColumn(EmbroideryElement):
_('Random percentage of satin width increase'),
tooltip=_('lengthen stitch across rails at most this percent. '
'Two values separated by a space may be used for an aysmmetric effect.'),
- default=0, type='float', unit="% (each side)", sort_index=90)
+ default=0, type='float', unit=_("% (each side)"), sort_index=90)
@cache
def random_width_increase(self):
return self.get_split_float_param("random_width_increase_percent", (0, 0)) / 100
@@ -202,7 +202,7 @@ class SatinColumn(EmbroideryElement):
_('Pull compensation percentage'),
tooltip=_('Additional pull compensation which varies as a percentage of stitch width. '
'Two values separated by a space may be used for an aysmmetric effect.'),
- unit='% (each side)',
+ unit=_('% (each side)'),
type='float',
default=0,
sort_index=6)
@@ -218,7 +218,7 @@ class SatinColumn(EmbroideryElement):
tooltip=_('Satin stitches pull the fabric together, resulting in a column narrower than you draw in Inkscape. '
'This setting expands each pair of needle penetrations outward from the center of the satin column by a fixed length. '
'Two values separated by a space may be used for an aysmmetric effect.'),
- unit='mm (each side)',
+ unit=_('mm (each side)'),
type='float',
default=0,
sort_index=7)
@@ -314,7 +314,7 @@ class SatinColumn(EmbroideryElement):
_('Inset distance (fixed)'),
tooltip=_('Shrink the outline by a fixed length, to prevent the underlay from showing around the outside of the satin column.'),
group=_('Contour Underlay'),
- unit='mm (each side)',
+ unit=_('mm (each side)'),
type='float',
default=0.4,
sort_index=2)
@@ -329,7 +329,7 @@ class SatinColumn(EmbroideryElement):
tooltip=_('Shrink the outline by a proportion of the column width, '
'to prevent the underlay from showing around the outside of the satin column.'),
group=_('Contour Underlay'),
- unit='% (each side)', type='float', default=0,
+ unit=_('% (each side)'), type='float', default=0,
sort_index=3)
@cache
def contour_underlay_inset_percent(self):
@@ -389,7 +389,7 @@ class SatinColumn(EmbroideryElement):
@param('zigzag_underlay_inset_mm',
_('Inset amount (fixed)'),
tooltip=_('default: half of contour underlay inset'),
- unit='mm (each side)',
+ unit=_('mm (each side)'),
group=_('Zig-zag Underlay'),
type='float',
default="")
@@ -409,7 +409,7 @@ class SatinColumn(EmbroideryElement):
@param('zigzag_underlay_inset_percent',
_('Inset amount (proportional)'),
tooltip=_('default: half of contour underlay inset'),
- unit='% (each side)',
+ unit=_('% (each side)'),
group=_('Zig-zag Underlay'),
type='float',
default="")
diff --git a/lib/extensions/zigzag_line_to_satin.py b/lib/extensions/zigzag_line_to_satin.py
index 5ff76be7..167f4b91 100644
--- a/lib/extensions/zigzag_line_to_satin.py
+++ b/lib/extensions/zigzag_line_to_satin.py
@@ -30,21 +30,40 @@ class ZigzagLineToSatin(InkstitchExtension):
for node in self.svg.selection:
d = []
point_list = list(node.get_path().end_points)
+ # find duplicated nodes (= do not smooth)
+ point_list, sharp_edges = self._get_sharp_edge_nodes(point_list)
rails, rungs = self._get_rails_and_rungs(point_list)
- if self.options.rungs:
- if self.options.reduce_rungs and len(rungs) > 2:
- rungs = rungs[0::2]
- d.extend(self._rung_path(rungs))
if not self.options.smoothing:
for rail in rails:
d.append('M ' + ' '.join([str(point) for point in rail]))
else:
- d.append(self._smooth_path(rails))
+ rails, rungs = self._smooth_path(rails, rungs, sharp_edges)
+ d.append(rails)
+
+ if self.options.rungs:
+ if self.options.pattern != 'zigzag' and self.options.reduce_rungs and len(rungs) > 2:
+ rungs = rungs[0::2]
+ d.extend(self._rung_path(rungs))
node.set('d', " ".join(d))
node.set('inkstitch:satin_column', True)
+ def _get_sharp_edge_nodes(self, point_list):
+ points = []
+ sharp_edges = []
+ skip = False
+ for p0, p1 in zip(point_list[:-1], point_list[1:]):
+ if skip is True:
+ skip = False
+ continue
+ points.append(p0)
+ if inkex.DirectedLineSegment(p0, p1).length < 0.3:
+ sharp_edges.append(p0)
+ skip = True
+ points.append(p1)
+ return points, sharp_edges
+
def _get_rails_and_rungs(self, point_list):
if self.options.pattern == "sawtooth":
# sawtooth pattern: |/|/|/|
@@ -55,15 +74,18 @@ class ZigzagLineToSatin(InkstitchExtension):
# zigzag pattern: VVVVV
rails = [point_list[0::2], point_list[1::2]]
rail_points = [[], []]
+ rung_points = [[], []]
for i, rail in enumerate(rails):
for j, point in enumerate(rail):
if j == 0 or point in point_list[2::len(point_list)-3]:
rail_points[i].append(point)
+ rung_points[i].append(point)
continue
p0 = rail[j-1]
- rail_points[i].append(inkex.Vector2d(inkex.DirectedLineSegment(p0, point).point_at_ratio(0.5)))
rail_points[i].append(point)
- rungs = list(zip(*rail_points))
+ rung_points[i].append(inkex.Vector2d(inkex.DirectedLineSegment(p0, point).point_at_ratio(0.5)))
+ rung_points[i].append(point)
+ rungs = list(zip(*rung_points))
return rail_points, rungs
else:
# square pattern: |_|▔|_|▔|
@@ -86,10 +108,14 @@ class ZigzagLineToSatin(InkstitchExtension):
rungs.extend([[points[0], points[1]], [points[2], points[3]]])
return rails, rungs
- def _smooth_path(self, rails):
+ def _smooth_path(self, rails, rungs, sharp_edges): # noqa: C901
path_commands = []
- smoothing = 0.2
- for rail in rails:
+ new_rungs = []
+ k = [1, 0]
+ smoothing = 0.4
+ has_equal_rail_point_count = len(rails[0]) == len(rails[1])
+ for j, rail in enumerate(rails):
+ r = rungs[j:len(rungs):2]
for i, point in enumerate(rail):
if i == 0:
path_commands.append(inkex.paths.Move(*point))
@@ -99,7 +125,9 @@ class ZigzagLineToSatin(InkstitchExtension):
prev_prev = rail[i - 1]
else:
prev_prev = rail[i-2]
+
prev = rail[i-1]
+
if i > len(rail) - 2:
next = point
else:
@@ -108,21 +136,54 @@ class ZigzagLineToSatin(InkstitchExtension):
# get length of handles
length = inkex.DirectedLineSegment(point, prev).length * smoothing
- # get handle positions
+ # get start handle positions
start = inkex.DirectedLineSegment(prev_prev, point)
- end = inkex.DirectedLineSegment(next, prev)
- if not start.length == 0:
+ if prev in sharp_edges:
+ start = prev
+ elif not start.length == 0:
start = start.parallel(*prev).point_at_length(start.length - length)
else:
start = start.start
- if not end.length == 0:
+
+ # get end handle positions
+ end = inkex.DirectedLineSegment(next, prev)
+ if point in sharp_edges:
+ end = point
+ elif not end.length == 0:
end = end.parallel(*point).point_at_length(end.length - length)
else:
end = end.start
# generate curves
path_commands.append(inkex.paths.Curve(*start, *end, *point))
- return str(inkex.Path(path_commands))
+
+ # recalculate rungs for zigzag pattern
+ if self.options.pattern == 'zigzag' and (has_equal_rail_point_count or i <= len(r)) and (not self.options.reduce_rungs or j == 0):
+ # in zigzag mode we do have alternating points on rails
+ # when smoothing them out, rungs may not intersect anymore
+ # so we need to find a spot on the smoothed rail to ensure the correct length
+ rung = r[i-1]
+ line = inkex.DirectedLineSegment(rung[0], rung[1])
+ point0 = line.point_at_length(-50)
+ point1 = line.point_at_length(line.length + 50)
+ new_point = inkex.bezier.linebezierintersect((point0, point1), [prev, start, end, point])
+ if new_point:
+ new_rungs.append((rung[k[j]], new_point[0]))
+ else:
+ new_rungs.append(rung)
+
+ rungs = self._update_rungs(new_rungs, rungs, r, has_equal_rail_point_count)
+ return str(inkex.Path(path_commands)), rungs
+
+ def _update_rungs(self, new_rungs, rungs, r, has_equal_rail_point_count):
+ if self.options.pattern == 'zigzag':
+ rungs = new_rungs
+ if not has_equal_rail_point_count and not self.options.reduce_rungs:
+ # make sure, that the last rail on canvas is also the last rail in the list
+ # this important when we delete the very first and very last rung
+ count = len(r)
+ rungs[count], rungs[-1] = rungs[-1], rungs[count]
+ return rungs
def _rung_path(self, rungs):
if len(rungs) < 3:
diff --git a/lib/stitches/ripple_stitch.py b/lib/stitches/ripple_stitch.py
index 40a522eb..90dc7cbc 100644
--- a/lib/stitches/ripple_stitch.py
+++ b/lib/stitches/ripple_stitch.py
@@ -235,8 +235,8 @@ def _adjust_helper_lines_for_grid(stroke, helper_lines, skip_start, skip_end):
if stroke.join_style == 0 and (stroke.reverse and count % 2 != 0):
count += 1
- elif (stroke.join_style == 1 and ((stroke.reverse and skip_end % 2 != 0) or
- (not stroke.reverse and skip_start % 2 != 0))):
+ elif (stroke.join_style == 1 and ((stroke.reverse and (count + skip_start) % 2 != 0) or
+ (not stroke.reverse and skip_start % 2 != 0))):
count += 1
if count % 2 != 0:
@@ -246,14 +246,15 @@ def _adjust_helper_lines_for_grid(stroke, helper_lines, skip_start, skip_end):
def _do_grid(stroke, helper_lines, skip_start, skip_end):
helper_lines = _adjust_helper_lines_for_grid(stroke, helper_lines, skip_start, skip_end)
+ grid = []
for i, helper in enumerate(helper_lines):
end = len(helper) - skip_end
points = helper[skip_start:end]
- if i % 2 == 0:
- points.reverse()
if stroke.reverse:
points.reverse()
- yield from points
+ grid.append(points)
+ grid = _get_staggered_stitches(stroke, grid, 0)
+ return grid
def _get_guided_helper_lines(stroke, outline, max_distance):