kopia lustrzana https://github.com/inkstitch/inkstitch
Add ripple stitch feature (#1667)
rodzic
ca07b1b267
commit
e968f814f7
|
@ -171,7 +171,7 @@ jobs:
|
|||
# with --no-binary argument may fix notary issues as well shapely speedups error issue
|
||||
pip install -U lxml --no-binary lxml
|
||||
pip uninstall --yes shapely
|
||||
pip install -v -U Shapely --no-binary Shapely
|
||||
pip install -v -U Shapely==1.8.1 --no-binary Shapely
|
||||
pip install pyinstaller
|
||||
|
||||
echo "${{ env.pythonLocation }}/bin" >> $GITHUB_PATH
|
||||
|
|
|
@ -26,6 +26,9 @@ COMMANDS = {
|
|||
# L10N command attached to an object
|
||||
"fill_end": N_("Fill stitch ending position"),
|
||||
|
||||
# L10N command attached to an object
|
||||
"ripple_target": N_("Ripple stitch target position"),
|
||||
|
||||
# L10N command attached to an object
|
||||
"run_start": N_("Auto-route running stitch starting position"),
|
||||
|
||||
|
@ -60,7 +63,8 @@ COMMANDS = {
|
|||
"stop_position": N_("Jump destination for Stop commands (a.k.a. \"Frame Out position\")."),
|
||||
}
|
||||
|
||||
OBJECT_COMMANDS = ["fill_start", "fill_end", "run_start", "run_end", "satin_start", "satin_end", "stop", "trim", "ignore_object", "satin_cut_point"]
|
||||
OBJECT_COMMANDS = ["fill_start", "fill_end", "ripple_target", "run_start", "run_end", "satin_start", "satin_end",
|
||||
"stop", "trim", "ignore_object", "satin_cut_point"]
|
||||
FREE_MOVEMENT_OBJECT_COMMANDS = ["run_start", "run_end", "satin_start", "satin_end"]
|
||||
LAYER_COMMANDS = ["ignore_layer"]
|
||||
GLOBAL_COMMANDS = ["origin", "stop_position"]
|
||||
|
|
|
@ -7,16 +7,30 @@ import sys
|
|||
|
||||
import shapely.geometry
|
||||
|
||||
from .element import EmbroideryElement, param
|
||||
from inkex import Transform
|
||||
|
||||
from ..i18n import _
|
||||
from ..stitch_plan import StitchGroup
|
||||
from ..stitches import bean_stitch, running_stitch
|
||||
from ..svg import parse_length_with_units
|
||||
from ..stitches.ripple_stitch import ripple_stitch
|
||||
from ..svg import get_node_transform, parse_length_with_units
|
||||
from ..utils import Point, cache
|
||||
from .element import EmbroideryElement, param
|
||||
from .satin_column import SatinColumn
|
||||
from .validation import ValidationWarning
|
||||
|
||||
warned_about_legacy_running_stitch = False
|
||||
|
||||
|
||||
class IgnoreSkipValues(ValidationWarning):
|
||||
name = _("Ignore skip")
|
||||
description = _("Skip values are ignored, because there was no line left to embroider.")
|
||||
steps_to_solve = [
|
||||
_('* Reduce values of Skip first and last lines or'),
|
||||
_('* Increase number of lines accordinly in the params dialog.'),
|
||||
]
|
||||
|
||||
|
||||
class Stroke(EmbroideryElement):
|
||||
element_name = _("Stroke")
|
||||
|
||||
|
@ -34,15 +48,36 @@ class Stroke(EmbroideryElement):
|
|||
return self.get_style("stroke-dasharray") is not None
|
||||
|
||||
@property
|
||||
@param('running_stitch_length_mm',
|
||||
_('Running stitch length'),
|
||||
tooltip=_('Length of stitches in running stitch mode.'),
|
||||
unit='mm',
|
||||
type='float',
|
||||
default=1.5,
|
||||
sort_index=3)
|
||||
def running_stitch_length(self):
|
||||
return max(self.get_float_param("running_stitch_length_mm", 1.5), 0.01)
|
||||
@param('stroke_method',
|
||||
_('Method'),
|
||||
type='dropdown',
|
||||
default=0,
|
||||
# 0: run/simple satin, 1: manual, 2: ripple
|
||||
options=[_("Running Stitch"), _("Ripple")],
|
||||
sort_index=0)
|
||||
def stroke_method(self):
|
||||
return self.get_int_param('stroke_method', 0)
|
||||
|
||||
@property
|
||||
@param('manual_stitch',
|
||||
_('Manual stitch placement'),
|
||||
tooltip=_("Stitch every node in the path. All other options are ignored."),
|
||||
type='boolean',
|
||||
default=False,
|
||||
select_items=[('stroke_method', 0)],
|
||||
sort_index=1)
|
||||
def manual_stitch_mode(self):
|
||||
return self.get_boolean_param('manual_stitch')
|
||||
|
||||
@property
|
||||
@param('repeats',
|
||||
_('Repeats'),
|
||||
tooltip=_('Defines how many times to run down and back along the path.'),
|
||||
type='int',
|
||||
default="1",
|
||||
sort_index=2)
|
||||
def repeats(self):
|
||||
return max(1, self.get_int_param("repeats", 1))
|
||||
|
||||
@property
|
||||
@param(
|
||||
|
@ -53,10 +88,93 @@ class Stroke(EmbroideryElement):
|
|||
'A value of 2 would quintuple each stitch, etc. Only applies to running stitch.'),
|
||||
type='int',
|
||||
default=0,
|
||||
sort_index=2)
|
||||
sort_index=3)
|
||||
def bean_stitch_repeats(self):
|
||||
return self.get_int_param("bean_stitch_repeats", 0)
|
||||
|
||||
@property
|
||||
@param('running_stitch_length_mm',
|
||||
_('Running stitch length'),
|
||||
tooltip=_('Length of stitches in running stitch mode.'),
|
||||
unit='mm',
|
||||
type='float',
|
||||
default=1.5,
|
||||
sort_index=4)
|
||||
def running_stitch_length(self):
|
||||
return max(self.get_float_param("running_stitch_length_mm", 1.5), 0.01)
|
||||
|
||||
@property
|
||||
@param('line_count',
|
||||
_('Number of lines'),
|
||||
tooltip=_('Number of lines from start to finish'),
|
||||
type='int',
|
||||
default=10,
|
||||
select_items=[('stroke_method', 1)],
|
||||
sort_index=5)
|
||||
@cache
|
||||
def line_count(self):
|
||||
return max(self.get_int_param("line_count", 10), 1)
|
||||
|
||||
@property
|
||||
@param('skip_start',
|
||||
_('Skip first lines'),
|
||||
tooltip=_('Skip this number of lines at the beginning.'),
|
||||
type='int',
|
||||
default=0,
|
||||
select_items=[('stroke_method', 1)],
|
||||
sort_index=6)
|
||||
@cache
|
||||
def skip_start(self):
|
||||
return abs(self.get_int_param("skip_start", 0))
|
||||
|
||||
@property
|
||||
@param('skip_end',
|
||||
_('Skip last lines'),
|
||||
tooltip=_('Skip this number of lines at the end'),
|
||||
type='int',
|
||||
default=0,
|
||||
select_items=[('stroke_method', 1)],
|
||||
sort_index=7)
|
||||
@cache
|
||||
def skip_end(self):
|
||||
return abs(self.get_int_param("skip_end", 0))
|
||||
|
||||
@property
|
||||
@param('flip',
|
||||
_('Flip'),
|
||||
tooltip=_('Flip outer to inner'),
|
||||
type='boolean',
|
||||
default=False,
|
||||
select_items=[('stroke_method', 1)],
|
||||
sort_index=8)
|
||||
@cache
|
||||
def flip(self):
|
||||
return self.get_boolean_param("flip", False)
|
||||
|
||||
@property
|
||||
@param('render_grid',
|
||||
_('Grid distance'),
|
||||
tooltip=_('Render as grid. Works only with satin type ripple stitches.'),
|
||||
type='float',
|
||||
default=0,
|
||||
select_items=[('stroke_method', 1)],
|
||||
sort_index=8)
|
||||
@cache
|
||||
def render_grid(self):
|
||||
return abs(self.get_float_param("render_grid", 0))
|
||||
|
||||
@property
|
||||
@param('exponent',
|
||||
_('Line distance exponent'),
|
||||
tooltip=_('Increse density towards one side.'),
|
||||
type='float',
|
||||
default=1,
|
||||
select_items=[('stroke_method', 1)],
|
||||
sort_index=9)
|
||||
@cache
|
||||
def exponent(self):
|
||||
return max(self.get_float_param("exponent", 1), 0.1)
|
||||
|
||||
@property
|
||||
@param('zigzag_spacing_mm',
|
||||
_('Zig-zag spacing (peak-to-peak)'),
|
||||
|
@ -64,22 +182,12 @@ class Stroke(EmbroideryElement):
|
|||
unit='mm',
|
||||
type='float',
|
||||
default=0.4,
|
||||
sort_index=3)
|
||||
select_items=[('stroke_method', 0)],
|
||||
sort_index=5)
|
||||
@cache
|
||||
def zigzag_spacing(self):
|
||||
return max(self.get_float_param("zigzag_spacing_mm", 0.4), 0.01)
|
||||
|
||||
@property
|
||||
@param('repeats',
|
||||
_('Repeats'),
|
||||
tooltip=_('Defines how many times to run down and back along the path.'),
|
||||
type='int',
|
||||
default="1",
|
||||
sort_index=1)
|
||||
def repeats(self):
|
||||
repeats = self.get_int_param("repeats", 1)
|
||||
return max(1, repeats)
|
||||
|
||||
@property
|
||||
def paths(self):
|
||||
path = self.parse_path()
|
||||
|
@ -102,18 +210,17 @@ class Stroke(EmbroideryElement):
|
|||
@cache
|
||||
def as_multi_line_string(self):
|
||||
line_strings = [shapely.geometry.LineString(path) for path in self.paths]
|
||||
|
||||
return shapely.geometry.MultiLineString(line_strings)
|
||||
|
||||
@property
|
||||
@param('manual_stitch',
|
||||
_('Manual stitch placement'),
|
||||
tooltip=_("Stitch every node in the path. Stitch length and zig-zag spacing are ignored."),
|
||||
type='boolean',
|
||||
default=False,
|
||||
sort_index=0)
|
||||
def manual_stitch_mode(self):
|
||||
return self.get_boolean_param('manual_stitch')
|
||||
def get_ripple_target(self):
|
||||
command = self.get_command('ripple_target')
|
||||
if command:
|
||||
pos = [float(command.use.get("x", 0)), float(command.use.get("y", 0))]
|
||||
transform = get_node_transform(command.use)
|
||||
pos = Transform(transform).apply_to_point(pos)
|
||||
return Point(*pos)
|
||||
else:
|
||||
return self.shape.centroid
|
||||
|
||||
def is_running_stitch(self):
|
||||
# using stroke width <= 0.5 pixels to indicate running stitch is deprecated in favor of dashed lines
|
||||
|
@ -199,23 +306,61 @@ class Stroke(EmbroideryElement):
|
|||
|
||||
return StitchGroup(self.color, stitches)
|
||||
|
||||
def do_bean_repeats(self, stitches):
|
||||
return bean_stitch(stitches, self.bean_stitch_repeats)
|
||||
|
||||
def to_stitch_groups(self, last_patch):
|
||||
patches = []
|
||||
|
||||
for path in self.paths:
|
||||
path = [Point(x, y) for x, y in path]
|
||||
if self.manual_stitch_mode:
|
||||
patch = StitchGroup(color=self.color, stitches=path, stitch_as_is=True)
|
||||
elif self.is_running_stitch():
|
||||
patch = self.running_stitch(path, self.running_stitch_length)
|
||||
|
||||
if self.bean_stitch_repeats > 0:
|
||||
patch.stitches = bean_stitch(patch.stitches, self.bean_stitch_repeats)
|
||||
|
||||
else:
|
||||
patch = self.simple_satin(path, self.zigzag_spacing, self.stroke_width)
|
||||
|
||||
# ripple stitch
|
||||
if self.stroke_method == 1:
|
||||
lines = self.as_multi_line_string()
|
||||
points = []
|
||||
if len(lines.geoms) > 1:
|
||||
# if render_grid has a number use this, otherwise use running_stitch_length
|
||||
length = self.render_grid or self.running_stitch_length
|
||||
# use satin column points for satin like build ripple stitches
|
||||
points = SatinColumn(self.node).plot_points_on_rails(length, 0)
|
||||
point_target = self.get_ripple_target()
|
||||
patch = StitchGroup(
|
||||
color=self.color,
|
||||
tags=["ripple_stitch"],
|
||||
stitches=ripple_stitch(
|
||||
self.as_multi_line_string(),
|
||||
point_target,
|
||||
self.line_count,
|
||||
points,
|
||||
self.running_stitch_length,
|
||||
self.repeats,
|
||||
self.flip,
|
||||
self.skip_start,
|
||||
self.skip_end,
|
||||
self.render_grid,
|
||||
self.exponent))
|
||||
if patch:
|
||||
if self.bean_stitch_repeats > 0:
|
||||
patch.stitches = self.do_bean_repeats(patch.stitches)
|
||||
patches.append(patch)
|
||||
else:
|
||||
for path in self.paths:
|
||||
path = [Point(x, y) for x, y in path]
|
||||
# manual stitch
|
||||
if self.manual_stitch_mode:
|
||||
patch = StitchGroup(color=self.color, stitches=path, stitch_as_is=True)
|
||||
# running stitch
|
||||
elif self.is_running_stitch():
|
||||
patch = self.running_stitch(path, self.running_stitch_length)
|
||||
if self.bean_stitch_repeats > 0:
|
||||
patch.stitches = self.do_bean_repeats(patch.stitches)
|
||||
# simple satin
|
||||
else:
|
||||
patch = self.simple_satin(path, self.zigzag_spacing, self.stroke_width)
|
||||
|
||||
if patch:
|
||||
patches.append(patch)
|
||||
|
||||
return patches
|
||||
|
||||
def validation_warnings(self):
|
||||
if self.stroke_method == 1 and self.skip_start + self.skip_end >= self.line_count:
|
||||
yield IgnoreSkipValues(self.shape.centroid)
|
||||
|
|
|
@ -129,6 +129,7 @@ class ParamsTab(ScrolledPanel):
|
|||
|
||||
self.update_choice_widgets((param, selection))
|
||||
self.settings_grid.Layout()
|
||||
self.Fit()
|
||||
self.Layout()
|
||||
|
||||
if event:
|
||||
|
|
|
@ -9,4 +9,5 @@ from .guided_fill import guided_fill
|
|||
from .running_stitch import *
|
||||
|
||||
# Can't put this here because we get a circular import :(
|
||||
#from auto_satin import auto_satin
|
||||
# from .auto_satin import auto_satin
|
||||
# from .ripple_stitch import ripple_stitch
|
||||
|
|
|
@ -132,7 +132,7 @@ def autorun(elements, preserve_order=False, break_up=None, starting_point=None,
|
|||
else:
|
||||
parent = elements[0].node.getparent()
|
||||
insert_index = parent.index(elements[0].node)
|
||||
group = create_new_group(parent, insert_index, _("Auto-Run"))
|
||||
group = create_new_group(parent, insert_index, _("Auto-Route"))
|
||||
add_elements_to_group(new_elements, group)
|
||||
|
||||
if trim:
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
from collections import defaultdict
|
||||
|
||||
from shapely.geometry import LineString, Point
|
||||
|
||||
from ..utils.geometry import line_string_to_point_list
|
||||
from .running_stitch import running_stitch
|
||||
|
||||
|
||||
def ripple_stitch(lines, target, line_count, points, max_stitch_length, repeats, flip, skip_start, skip_end, render_grid, exponent):
|
||||
'''
|
||||
Ripple stitch is allowed to cross itself and doesn't care about an equal distance of lines
|
||||
It is meant to be used with light (not dense) stitching
|
||||
It will ignore holes in a closed shape. Closed shapes will be filled with a spiral
|
||||
Open shapes will be stitched back and forth.
|
||||
If there is only one (open) line or a closed shape the target point will be used.
|
||||
If more sublines are present interpolation will take place between the first two.
|
||||
'''
|
||||
|
||||
# sort geoms by size
|
||||
lines = sorted(lines.geoms, key=lambda linestring: linestring.length, reverse=True)
|
||||
outline = lines[0]
|
||||
|
||||
# ignore skip_start and skip_end if both toghether are greater or equal to line_count
|
||||
if skip_start + skip_end >= line_count:
|
||||
skip_start = skip_end = 0
|
||||
|
||||
if is_closed(outline):
|
||||
rippled_line = do_circular_ripple(outline, target, line_count, repeats, flip, max_stitch_length, skip_start, skip_end, exponent)
|
||||
else:
|
||||
rippled_line = do_linear_ripple(lines, points, target, line_count - 1, repeats, flip, skip_start, skip_end, render_grid, exponent)
|
||||
|
||||
return running_stitch(line_string_to_point_list(rippled_line), max_stitch_length)
|
||||
|
||||
|
||||
def do_circular_ripple(outline, target, line_count, repeats, flip, max_stitch_length, skip_start, skip_end, exponent):
|
||||
# for each point generate a line going to the target point
|
||||
lines = target_point_lines_normalized_distances(outline, target, flip, max_stitch_length)
|
||||
|
||||
# create a list of points for each line
|
||||
points = get_interpolation_points(lines, line_count, exponent, "circular")
|
||||
|
||||
# connect the lines to a spiral towards the target
|
||||
coords = []
|
||||
for i in range(skip_start, line_count - skip_end):
|
||||
for j in range(len(lines)):
|
||||
coords.append(Point(points[j][i].x, points[j][i].y))
|
||||
|
||||
coords = repeat_coords(coords, repeats)
|
||||
|
||||
return LineString(coords)
|
||||
|
||||
|
||||
def do_linear_ripple(lines, points, target, line_count, repeats, flip, skip_start, skip_end, render_grid, exponent):
|
||||
if len(lines) == 1:
|
||||
helper_lines = target_point_lines(lines[0], target, flip)
|
||||
else:
|
||||
helper_lines = []
|
||||
for start, end in zip(points[0], points[1]):
|
||||
if flip:
|
||||
helper_lines.append(LineString([end, start]))
|
||||
else:
|
||||
helper_lines.append(LineString([start, end]))
|
||||
|
||||
# get linear points along the lines
|
||||
points = get_interpolation_points(helper_lines, line_count, exponent)
|
||||
|
||||
# go back and forth along the lines - flip direction of every second line
|
||||
coords = []
|
||||
for i in range(skip_start, len(points[0]) - skip_end):
|
||||
for j in range(len(helper_lines)):
|
||||
k = j
|
||||
if i % 2 != 0:
|
||||
k = len(helper_lines) - j - 1
|
||||
coords.append(Point(points[k][i].x, points[k][i].y))
|
||||
|
||||
# add helper lines as a grid
|
||||
# for now only add this to satin type ripples, otherwise it could become to dense at the target point
|
||||
if len(lines) > 1 and render_grid:
|
||||
coords.extend(do_grid(helper_lines, line_count - skip_end))
|
||||
|
||||
coords = repeat_coords(coords, repeats)
|
||||
|
||||
return LineString(coords)
|
||||
|
||||
|
||||
def do_grid(lines, num_lines):
|
||||
coords = []
|
||||
if num_lines % 2 == 0:
|
||||
lines = reversed(lines)
|
||||
for i, line in enumerate(lines):
|
||||
line_coords = list(line.coords)
|
||||
if (i % 2 == 0 and num_lines % 2 == 0) or (i % 2 != 0 and num_lines % 2 != 0):
|
||||
coords.extend(reversed(line_coords))
|
||||
else:
|
||||
coords.extend(line_coords)
|
||||
return coords
|
||||
|
||||
|
||||
def line_length(line):
|
||||
return line.length
|
||||
|
||||
|
||||
def is_closed(line):
|
||||
coords = line.coords
|
||||
return Point(*coords[0]).distance(Point(*coords[-1])) < 0.05
|
||||
|
||||
|
||||
def target_point_lines(outline, target, flip):
|
||||
lines = []
|
||||
for point in outline.coords:
|
||||
if flip:
|
||||
lines.append(LineString([point, target]))
|
||||
else:
|
||||
lines.append(LineString([target, point]))
|
||||
return lines
|
||||
|
||||
|
||||
def target_point_lines_normalized_distances(outline, target, flip, max_stitch_length):
|
||||
lines = []
|
||||
outline = running_stitch(line_string_to_point_list(outline), max_stitch_length)
|
||||
for point in outline:
|
||||
if flip:
|
||||
lines.append(LineString([target, point]))
|
||||
else:
|
||||
lines.append(LineString([point, target]))
|
||||
return lines
|
||||
|
||||
|
||||
def get_interpolation_points(lines, line_count, exponent, method="linear"):
|
||||
new_points = defaultdict(list)
|
||||
count = len(lines) - 1
|
||||
for i, line in enumerate(lines):
|
||||
steps = get_steps(line, line_count, exponent)
|
||||
distance = -1
|
||||
points = []
|
||||
for j in range(line_count):
|
||||
length = line.length * steps[j]
|
||||
if method == "circular":
|
||||
if distance == -1:
|
||||
# the first line makes sure, it is going to be a spiral
|
||||
distance = (line.length * steps[j+1]) * (i / count)
|
||||
else:
|
||||
distance += length - (line.length * steps[j-1])
|
||||
else:
|
||||
distance = line.length * steps[j]
|
||||
points.append(line.interpolate(distance))
|
||||
if method == "linear":
|
||||
points.append(Point(*line.coords[-1]))
|
||||
new_points[i] = points
|
||||
return new_points
|
||||
|
||||
|
||||
def get_steps(line, total_lines, exponent):
|
||||
# get_steps is scribbled from the inkscape interpolate extension
|
||||
# (https://gitlab.com/inkscape/extensions/-/blob/master/interp.py)
|
||||
steps = [
|
||||
((i + 1) / (total_lines)) ** exponent
|
||||
for i in range(total_lines - 1)
|
||||
]
|
||||
return [0] + steps + [1]
|
||||
|
||||
|
||||
def repeat_coords(coords, repeats):
|
||||
final_coords = []
|
||||
for i in range(repeats):
|
||||
if i % 2 == 1:
|
||||
# reverse every other pass
|
||||
this_coords = coords[::-1]
|
||||
else:
|
||||
this_coords = coords[:]
|
||||
|
||||
final_coords.extend(this_coords)
|
||||
return final_coords
|
|
@ -63,6 +63,11 @@ inkstitch_attribs = [
|
|||
'join_style',
|
||||
'avoid_self_crossing',
|
||||
'clockwise',
|
||||
'line_count',
|
||||
'skip_start',
|
||||
'skip_end',
|
||||
'render_grid',
|
||||
'exponent',
|
||||
'expand_mm',
|
||||
'fill_underlay',
|
||||
'fill_underlay_angle',
|
||||
|
@ -80,7 +85,7 @@ inkstitch_attribs = [
|
|||
'flip',
|
||||
'expand_mm',
|
||||
# stroke
|
||||
'manual_stitch',
|
||||
'stroke_method',
|
||||
'bean_stitch_repeats',
|
||||
'repeats',
|
||||
'running_stitch_length_mm',
|
||||
|
@ -102,7 +107,8 @@ inkstitch_attribs = [
|
|||
'stroke_first',
|
||||
# Legacy
|
||||
'trim_after',
|
||||
'stop_after'
|
||||
'stop_after',
|
||||
'manual_stitch',
|
||||
]
|
||||
for attrib in inkstitch_attribs:
|
||||
INKSTITCH_ATTRIBS[attrib] = inkex.addNS(attrib, 'inkstitch')
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
backports.functools_lru_cache
|
||||
wxPython
|
||||
networkx
|
||||
shapely==1.8.0
|
||||
shapely==1.8.2
|
||||
lxml
|
||||
appdirs
|
||||
numpy<=1.17.4
|
||||
|
|
|
@ -324,6 +324,22 @@
|
|||
id="inkstitch-autorun_end-path"
|
||||
d="M -1.5977169,-4.8605484 c -0.00319,1.523e-4 -0.00643,6.284e-4 -0.00955,0.00139 l -1.738218,0.6114515 c -0.044131,0.013274 -0.04771,0.07406 -0.00546,0.092381 l 1.7286718,0.6522048 c 0.042543,0.011464 0.077832,-0.033916 0.055977,-0.072004 -0.075631,-0.1076723 -0.1279528,-0.2256474 -0.1583813,-0.3478501 l 5.3580083,0.0693 C 3.7283489,-3.6574881 3.9289854,-3.5209456 4.163113,-3.51807 4.4929661,-3.51396 4.7679522,-3.7755203 4.7721242,-4.1036793 4.7763142,-4.4318766 4.5079699,-4.70559 4.178155,-4.7096844 3.9431472,-4.7126044 3.7385104,-4.5784741 3.6388043,-4.38223 l -5.3566689,-0.065225 c 0.033509,-0.1204507 0.089391,-0.2361787 0.1679695,-0.3396805 0.019712,-0.034678 -0.00793,-0.077126 -0.047786,-0.073375 z m -2.6203001,0.2119742 c -0.3227531,0.0041 -0.5844387,0.2625539 -0.5884958,0.5856093 -0.00295,0.2329983 0.129063,0.4383262 0.3236143,0.5394287 l -0.065546,5.2964025 c -0.1188053,-0.03344 -0.233209,-0.088553 -0.3359005,-0.1657553 -0.018028,-0.014169 -0.043442,-0.014169 -0.061451,0 -0.016535,0.013426 -0.022582,0.035878 -0.015004,0.055721 l 0.6130875,1.7310434 c 0.013338,0.043896 0.074426,0.047476 0.092855,0.00543 l 0.6608737,-1.7201931 c 0.021243,-0.048142 -0.037912,-0.091505 -0.077832,-0.057054 -0.1085476,0.075489 -0.2269701,0.1273635 -0.3495646,0.1576047 l 0.069641,-5.2950505 c 0.1995845,-0.095713 0.3397855,-0.2989653 0.3427327,-0.5326301 0.00412,-0.3281781 -0.2641734,-0.5964641 -0.5939692,-0.6005585 -0.00519,-7.62e-5 -0.00991,-7.62e-5 -0.015023,0 z m 8.4425639,1.3302136 c -0.020458,-1.333e-4 -0.038925,0.012283 -0.046428,0.03125 l -0.6608735,1.714742 c -0.021243,0.04818 0.037931,0.091524 0.077851,0.057054 0.1072273,-0.074556 0.2244441,-0.1271727 0.3454502,-0.1576044 L 3.8750009,3.6234841 C 3.6760287,3.7194257 3.5366315,3.9202022 3.5336461,4.15341 3.529436,4.4816071 3.7964416,4.7512453 4.1262565,4.7553397 4.4560331,4.759449 4.726962,4.4979085 4.731134,4.1697112 4.7341354,3.934523 4.5996979,3.7276145 4.4020654,3.6275594 L 4.4703294,-1.66612 c 0.1197239,0.033383 0.2338597,0.08802 0.3372785,0.1657745 0.039309,0.032355 0.096166,-0.00834 0.077832,-0.055721 L 4.2709744,-3.2871101 c -0.00748,-0.018949 -0.02595,-0.031384 -0.046428,-0.031251 z M 1.5114302,3.6180947 c -0.037451,6.856e-4 -0.060627,0.040868 -0.042351,0.073356 0.075823,0.1079391 0.1280103,0.2267139 0.1584006,0.3492023 L -3.7305473,3.971372 c -0.096108,-0.1988532 -0.2989079,-0.338138 -0.5338966,-0.3410517 -0.3297958,-0.0041 -0.5994042,0.2615256 -0.6035188,0.5896847 -0.00413,0.3281972 0.2627956,0.6019488 0.5926104,0.6060241 0.2345678,0.00292 0.4394534,-0.1304295 0.5393508,-0.3261024 l 5.3580084,0.063873 C 1.5885549,4.684593 1.5314859,4.7996924 1.4526979,4.90348 1.4299049,4.942272 1.4668789,4.9887 1.5100529,4.975503 L 3.2496085,4.3640511 c 0.043002,-0.015959 0.043002,-0.076441 0,-0.0924 L 1.5250561,3.6194659 c -0.00446,-0.00112 -0.00905,-0.00154 -0.013665,-0.00139 Z" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="inkstitch_ripple_target"
|
||||
style="display:inline">
|
||||
<title
|
||||
id="inkstitch_title9427-9">Ripple stitch target point</title>
|
||||
<path
|
||||
id="inkstitch_circle13166-9"
|
||||
d="m 9.220113,0.07922893 c -1.9e-6,5.10672897 -4.1398241,9.24654997 -9.24655297,9.24654997 -5.10672933,0 -9.24655213,-4.139821 -9.24655403,-9.24654997 1e-7,-2.45233803 0.9741879,-4.80423503 2.7082531,-6.53830103 1.7340653,-1.734065 4.0859624,-2.708252 6.53830093,-2.708252 5.10673007,0 9.24655277,4.139823 9.24655297,9.24655303 0,0 0,0 0,0"
|
||||
style="opacity:1;vector-effect:none;fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:#003399;stroke-width:1.06500006;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.19500017, 3.19500017;stroke-dashoffset:0;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:1;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;"
|
||||
d="m -4.1361006,-3.9974292 8.224564,8.224564 m 0,-8.224564 -8.224564,8.224564 m 9.927927,-4.112282 h -11.63129 m 5.81564501,-5.815645 v 11.63129"
|
||||
id="inkstitch_rect5371-2-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata8380">
|
||||
|
@ -458,5 +474,13 @@
|
|||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(37.830849,113.28861)" />
|
||||
<use
|
||||
xlink:href="#inkstitch_ripple_target"
|
||||
id="use37099"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(151.1811,112.79208)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Przed Szerokość: | Wysokość: | Rozmiar: 50 KiB Po Szerokość: | Wysokość: | Rozmiar: 51 KiB |
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Autoroute Running Stitch</name>
|
||||
<name>Auto-Route Running Stitch</name>
|
||||
<id>org.inkstitch.auto_run</id>
|
||||
<param name="extension" type="string" gui-hidden="true">auto_run</param>
|
||||
<effect>
|
||||
|
@ -12,7 +12,7 @@
|
|||
</effects-menu>
|
||||
</effect>
|
||||
<param name="options" type="notebook">
|
||||
<page name="options" gui-text="Autoroute Running Stitch Options">
|
||||
<page name="options" gui-text="Auto-Route Running Stitch Options">
|
||||
<spacer />
|
||||
<param name="break_up" type="boolean" gui-text="Add nodes at intersections">true</param>
|
||||
<spacer />
|
||||
|
@ -21,7 +21,7 @@
|
|||
<param name="trim" type="boolean" gui-text="Trim jump stitches">false</param>
|
||||
</page>
|
||||
<page name="help" gui-text="Help">
|
||||
<label appearance="header">Autoroute Running Stitch</label>
|
||||
<label appearance="header">Auto-Route Running Stitch</label>
|
||||
<label>Add nodes at intersections:</label>
|
||||
<spacer />
|
||||
<label indent="1">- Enabled (automatic). Ink/Stitch will add some nodes for better routing. This is the default setting.</label>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="Ink/Stitch">
|
||||
<submenu name="Ink/Stitch" translatable="no">
|
||||
<submenu name="Edit" />
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
|
|
Ładowanie…
Reference in New Issue