From b0105196889a463579aab21cd29bbf1abb96dab1 Mon Sep 17 00:00:00 2001
From: Kaalleen <36401965+kaalleen@users.noreply.github.com>
Date: Sat, 7 Dec 2024 15:20:11 +0100
Subject: Enable start end commands for satins (#3315)
Updates commands
fill_start (_end) => starting_point (_end)
stain_start (_end) and run_start (_end) => autoroute_start
ripple_target => target_point
Sets inkstitch svg version to 3
---
"fonts/Brockscript/\342\206\222.svg" | 66 --
"fonts/Shojumaru/\342\206\222.svg" | 142 ---
"fonts/abecedaire/\342\206\222.svg" | 57 -
.../\342\206\222/latin.svg" | 117 ---
"fonts/amitaclo/\342\206\222.svg" | 52 -
"fonts/amitaclo_small/\342\206\222.svg" | 55 -
"fonts/apex_lake/\342\206\222.svg" | 98 --
"fonts/apex_simple_AGS/\342\206\222.svg" | 67 --
"fonts/auberge_marif/\342\206\222.svg" | 144 ---
"fonts/auberge_small/\342\206\222.svg" | 144 ---
"fonts/aventurina/\342\206\222.svg" | 108 --
"fonts/baumans_FI/\342\206\220.svg" | 126 ---
"fonts/baumans_FI/\342\206\222.svg" | 46 +-
"fonts/baumans_FI_Small/\342\206\220.svg" | 126 ---
"fonts/baumans_FI_Small/\342\206\222.svg" | 45 +-
"fonts/cherryforinkstitch/\342\206\222.svg" | 66 --
"fonts/cherryforkaalleen/\342\206\222.svg" | 73 --
"fonts/chicken_little/\342\206\222.svg" | 75 --
"fonts/chicken_little_small/\342\206\222.svg" | 78 --
"fonts/chopin/\342\206\222.svg" | 86 --
"fonts/cogs_KOR/\342\206\222.svg" | 156 ---
"fonts/cooper_marif/\342\206\222.svg" | 1108 ++++++++++----------
"fonts/dejavufont/\342\206\221.svg" | 69 --
"fonts/digory_doodles_bean/\342\206\222.svg" | 117 ---
"fonts/emilio_20_applique/\342\206\222.svg" | 85 --
"fonts/emilio_20_bold/\342\206\222.svg" | 85 --
"fonts/emilio_20_tartan/\342\206\222.svg" | 147 ---
"fonts/espresso_KOR/\342\206\220.svg" | 42 -
"fonts/espresso_KOR/\342\206\222.svg" | 93 --
"fonts/espresso_tiny/\342\206\220.svg" | 42 -
"fonts/espresso_tiny/\342\206\222.svg" | 93 --
"fonts/excalibur_KOR/\342\206\222.svg" | 42 -
"fonts/excalibur_small/\342\206\222.svg" | 42 -
"fonts/glacial_tiny/\342\206\220.svg" | 104 --
"fonts/glacial_tiny/\342\206\222.svg" | 98 --
"fonts/honoka/\342\206\222/hiragana.svg" | 121 ---
"fonts/honoka/\342\206\222/jlpt5.svg" | 124 ---
"fonts/honoka/\342\206\222/katakana.svg" | 121 ---
"fonts/invercelia/\342\206\222.svg" | 86 +-
"fonts/kaushan_script_MAM/\342\206\222.svg" | 93 --
"fonts/lobster_AGS/\342\206\222.svg" | 102 --
"fonts/magnolia_KOR/\342\206\222.svg" | 45 -
"fonts/magnolia_bicolor/\342\206\222.svg" | 155 ---
"fonts/magnolia_small/\342\206\222.svg" | 45 -
"fonts/magnolia_tamed/\342\206\222.svg" | 155 ---
"fonts/manuskript_gotisch/\342\206\222.svg" | 80 --
"fonts/marcelusSC_FI/\342\206\222.svg" | 87 --
"fonts/medium_font/\342\206\222.svg" | 68 --
"fonts/milli_marif_bold/\342\206\222.svg" | 83 --
"fonts/namskout_AGS/\342\206\222.svg" | 63 --
"fonts/namskout_relief/\342\206\222.svg" | 129 ---
"fonts/namskout_tartan/\342\206\222.svg" | 101 --
"fonts/ondulamarif_Medium/\342\206\222.svg" | 24 +-
"fonts/ondulamarif_S/\342\206\222.svg" | 24 +-
"fonts/ondulamarif_XL/\342\206\222.svg" | 24 +-
"fonts/pacificlo/\342\206\222.svg" | 42 -
"fonts/pacificlo_tiny/\342\206\222.svg" | 42 -
"fonts/perspective_tricolore_KOR/\342\206\222.svg" | 166 ---
"fonts/roaring_twenties_KOR/\342\206\222.svg" | 119 ---
.../roaring_twenties_KOR_small/\342\206\222.svg" | 119 ---
"fonts/roman_ags/\342\206\220.svg" | 78 --
"fonts/roman_ags/\342\206\222.svg" | 63 --
"fonts/roman_ags_bicolor/\342\206\220/mono.svg" | 78 --
"fonts/roman_ags_bicolor/\342\206\220/zbi.svg" | 107 --
"fonts/roman_ags_bicolor/\342\206\222/mono.svg" | 63 --
"fonts/roman_ags_bicolor/\342\206\222/zbi.svg" | 66 --
lib/commands.py | 20 +-
lib/elements/fill_stitch.py | 14 +-
lib/elements/satin_column.py | 308 +++++-
lib/elements/stroke.py | 2 +-
lib/extensions/auto_run.py | 4 +-
lib/extensions/auto_satin.py | 4 +-
lib/extensions/cut_satin.py | 2 +
lib/extensions/gradient_blocks.py | 6 +-
lib/extensions/redwork.py | 4 +-
lib/svg/path.py | 3 +
lib/svg/tags.py | 2 +
lib/tartan/svg.py | 4 +-
lib/update.py | 42 +-
symbols/inkstitch.svg | 84 +-
tests/test_clone.py | 12 +-
81 files changed, 897 insertions(+), 6381 deletions(-)
diff --git "a/fonts/Brockscript/\342\206\222.svg" "b/fonts/Brockscript/\342\206\222.svg"
index 119d645d..a114ac06 100644
--- "a/fonts/Brockscript/\342\206\222.svg"
+++ "b/fonts/Brockscript/\342\206\222.svg"
@@ -94,72 +94,6 @@ Copyright (c) Typographer Mediengestaltung, 2000. All rights reserved.
id="min_stitch_len_mm6075">0.5
2
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Trim the thread after sewing this object.
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Fill stitch starting point
-
-
-
-
- Fill stitch ending point
-
-
-
-
- Running stitch ending point
-
-
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
-
0.5
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Fill stitch ending point
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Fill stitch starting point
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore object when generating stitch plan
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Fill stitch starting point
-
-
-
-
- Fill stitch ending point
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore object when generating stitch plan
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Fill stitch starting point
-
-
-
-
- Fill stitch ending point
-
-
-
-
- Fill stitch starting point
-
-
-
-
- Fill stitch ending point
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
image/svg+xml2.00.51Satin Column cut pointSatin column starting pointSatin column ending point0.51
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
2.00.51Satin Column cut pointSatin column starting pointSatin column ending point0
2
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
0.5
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
3
1
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Running stitch ending point
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
-
-
-
-
+ showguides="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1131"
+ inkscape:window-x="0"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1">
0.5
3.0
-2
+3
@@ -1099,7 +1104,7 @@ Created by FontForge 20201107 at Mon Jun 17 22:36:34 2024
id="hkern172" />
+ id="inkstitch_starting_point">
Fill stitch starting point
+ id="inkstitch_ending_point">
Fill stitch ending point
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
+ transform="translate(0, 123.307)">
+ transform="translate(267.987, -64.6349)">
+ transform="translate(-96.0262, 209.964)">
-
-
-
-
DejaVu serif semi condensed
-
- Trim the thread after sewing this object.
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
diff --git "a/fonts/digory_doodles_bean/\342\206\222.svg" "b/fonts/digory_doodles_bean/\342\206\222.svg"
index 75272a01..743415b8 100644
--- "a/fonts/digory_doodles_bean/\342\206\222.svg"
+++ "b/fonts/digory_doodles_bean/\342\206\222.svg"
@@ -103,123 +103,6 @@ SIL Open Font License (OFL)
id="min_stitch_len_mm6747">0
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Trim the thread after sewing this object.
-
-
-
-
- Running stitch starting point
-
-
-
-
- Running stitch ending point
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Trim the thread after sewing this object.
-
-
-
-
- Running stitch starting point
-
-
-
-
- Running stitch ending point
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Trim the thread after sewing this object.
-
-
-
-
- Running stitch starting point
-
-
-
-
- Running stitch ending point
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Fill stitch starting point
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
3.0
2
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
032
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
- 032
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
-
-
3
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Fill stitch ending point
-
-
-
-
0
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
0
2
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
-
-
-
-
-
0
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
0
2
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
-
-
-
-
-
3.0
1
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Fill stitch ending point
-
-
-
-
-
-
-
A
-
- Satin Column cut point
-
-
-
-
-
- Ignore object when generating stitch plan
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Running stitch ending point
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Fill stitch ending point
-
-
-
diff --git "a/fonts/milli_marif_bold/\342\206\222.svg" "b/fonts/milli_marif_bold/\342\206\222.svg"
index cd668e99..8a0cef35 100644
--- "a/fonts/milli_marif_bold/\342\206\222.svg"
+++ "b/fonts/milli_marif_bold/\342\206\222.svg"
@@ -705,89 +705,6 @@ Jeremy Landes
d="M40 59c0 -3 2 -6 5 -9c4 2 7 5 7 9c0 5 -3 5 -6 5s-6 0 -6 -5zM69 40v6h17v-6c0 -11 -2 -20 -8 -27l8 -8v-5h-19l-3 3c-6 -3 -14 -4 -24 -4c-22 0 -35 9 -35 29c0 12 8 18 21 20c-2 4 -4 9 -4 14c0 12 10 20 24 20c16 0 23 -6 23 -20c0 -9 -7 -18 -17 -21l14 -14 c2 4 3 7 3 13zM22 28c0 -7 6 -12 18 -12c4 0 8 0 11 1l-19 21c-8 -2 -10 -5 -10 -10z"
id="glyph109" />
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Running stitch starting point
-
-
-
-
- Running stitch ending point
-
-
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
-
-
-
-
-
-
-
Fill stitch ending pointFill stitch ending pointFill stitch ending pointFill stitch ending pointFill stitch ending pointFill stitch ending point
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Trim the thread after sewing this object.
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Fill stitch starting point
-
-
-
-
- Fill stitch ending point
-
-
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Running stitch starting point
-
-
-
-
- Running stitch ending point
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Running stitch starting point
-
-
-
-
- Running stitch ending point
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Fill stitch ending point
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Fill stitch ending point
-
-
-
3
2
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Ignore entire layer when generating stitch plan
-
-
-
-
-
-
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
0
2
-
-
- Satin column ending point
-
-
-
-
-
- Satin Column cut point
-
-
-
-
-
- Satin column starting point
-
-
-
-
-
1:
+ first, second = self.rail_indices
+ csp[first], csp[second] = csp[second], csp[first]
+
+ return self._csp_to_satin(csp)
+
def apply_transform(self):
"""Return a new SatinColumn like this one but with transforms applied.
@@ -837,6 +891,18 @@ class SatinColumn(EmbroideryElement):
if cut_points is None:
cut_points = self.find_cut_points(split_point)
path_lists = self._cut_rails(cut_points)
+
+ # prevent error when split points lies at the start or end of the satin column
+ cleaned_path_lists = path_lists
+ for i, path_list in enumerate(path_lists):
+ if None in path_list:
+ cleaned_path_lists[i] = None
+ continue
+ for path in path_list:
+ if shgeo.LineString(path).length < self.zigzag_spacing:
+ cleaned_path_lists[i] = None
+ path_lists = cleaned_path_lists
+
self._assign_rungs_to_split_rails(path_lists)
self._add_rungs_if_necessary(path_lists)
return [self._path_list_to_satins(path_list) for path_list in path_lists]
@@ -919,7 +985,8 @@ class SatinColumn(EmbroideryElement):
rungs = [shgeo.LineString(self.flatten_subpath(rung)) for rung in self.rungs]
for path_list in split_rails:
- path_list.extend(rung for rung in rungs if path_list[0].intersects(rung) and path_list[1].intersects(rung))
+ if path_list is not None:
+ path_list.extend(rung for rung in rungs if path_list[0].intersects(rung) and path_list[1].intersects(rung))
def _add_rungs_if_necessary(self, path_lists):
"""Add an additional rung to each new satin if needed.
@@ -936,6 +1003,8 @@ class SatinColumn(EmbroideryElement):
"""
for path_list in path_lists:
+ if path_list is None:
+ continue
if len(path_list) in (2, 4):
# Add the rung just after the start of the satin.
# If the rails have opposite directions it may end up at the end of the satin.
@@ -953,7 +1022,10 @@ class SatinColumn(EmbroideryElement):
path_list.append(rung)
def _path_list_to_satins(self, path_list):
- return self._csp_to_satin(line_strings_to_csp(path_list))
+ linestrings = line_strings_to_csp(path_list)
+ if not linestrings:
+ return None
+ return self._csp_to_satin(linestrings)
def _csp_to_satin(self, csp):
node = deepcopy(self.node)
@@ -1024,6 +1096,23 @@ class SatinColumn(EmbroideryElement):
center_walk = [center_walk[0], center_walk[0]]
return shgeo.LineString(center_walk)
+ @property
+ @cache
+ def offset_center_line(self):
+ stitches = self._get_center_line_stitches()
+ linestring = shgeo.LineString(stitches)
+ return linestring
+
+ def _get_center_line_stitches(self):
+ inset_prop = -np.array([self.running_stitch_position, 100-self.running_stitch_position]) / 100
+
+ # Do it like contour underlay, but inset all the way to the center.
+ pairs = self.plot_points_on_rails(self.running_stitch_tolerance, (0, 0), inset_prop)
+
+ points = [points[0] for points in pairs]
+ stitches = running_stitch.even_running_stitch(points, self.running_stitch_length, self.running_stitch_tolerance)
+ return stitches
+
def _stitch_distance(self, pos0, pos1, previous_pos0, previous_pos1):
"""Return the distance from one stitch to the next."""
@@ -1047,7 +1136,7 @@ class SatinColumn(EmbroideryElement):
return max(abs(d0 * normal), abs(d1 * normal))
@debug.time
- def plot_points_on_rails(self, spacing, offset_px=(0, 0), offset_proportional=(0, 0), use_random=False
+ def plot_points_on_rails(self, spacing, offset_px=(0, 0), offset_proportional=(0, 0), use_random=False,
) -> typing.List[typing.Tuple[Point, Point]]:
# Take a section from each rail in turn, and plot out an equal number
# of points on both rails. Return the points plotted. The points will
@@ -1158,6 +1247,75 @@ class SatinColumn(EmbroideryElement):
return pairs
+ def do_start_path(self, satins, start_point):
+ start_stitch_group = StitchGroup(
+ color=self.color,
+ tags=("satin_column", "satin_column_underlay"),
+ stitches=[Stitch(*start_point)]
+ )
+ connector = self.offset_center_line
+ split_line = shgeo.LineString(self.find_cut_points(start_point))
+ start = connector.project(nearest_points(split_line, connector)[1])
+
+ if self.end_point is None:
+ end = 0
+ elif satins[0] is None:
+ if self._center_walk_is_odd():
+ end = 0
+ else:
+ end = connector.length
+ elif satins[1] is None:
+ if self._center_walk_is_odd():
+ end = connector.length
+ else:
+ end = 0
+ else:
+ if not self._center_walk_is_odd():
+ end = 0
+ else:
+ split_line = shgeo.LineString(self.find_cut_points(self.end_point))
+ end = connector.project(nearest_points(split_line, connector)[1])
+
+ start_path = substring(connector, start, end)
+ stitches = [Stitch(*coord) for coord in start_path.coords]
+ stitch_group = StitchGroup(
+ color=self.color,
+ tags=("satin_column", "satin_column_underlay"),
+ stitches=stitches
+ )
+ stitch_group = self.connect_and_add(start_stitch_group, stitch_group)
+ return stitch_group
+
+ def do_end_point_connection(self):
+ if self._center_walk_is_odd():
+ return StitchGroup()
+ center_line = self.offset_center_line.reverse()
+ stitches = [Stitch(*coord) for coord in center_line.coords]
+ stitch_group = StitchGroup(
+ color=self.color,
+ tags=("satin_column", "satin_column_underlay"),
+ stitches=stitches
+ )
+ return stitch_group
+
+ def _do_underlay_stitch_groups(self, i, satin, stitch_group):
+ if self.center_walk_underlay:
+ center_walk = satin.do_center_walk()
+ stitch_group = self.connect_and_add(stitch_group, center_walk)
+
+ # if they just went one stitch back, it's not really necessary to add all the underlays
+ if i == 0 or satin.center_line.length > self.zigzag_spacing:
+ if self.contour_underlay:
+ contour = satin.do_contour_underlay()
+ stitch_group = self.connect_and_add(stitch_group, contour)
+
+ if self.zigzag_underlay:
+ # zigzag underlay comes after contour walk underlay, so that the
+ # zigzags sit on the contour walk underlay like rail ties on rails.
+ zigzag = satin.do_zigzag_underlay()
+ stitch_group = self.connect_and_add(stitch_group, zigzag)
+ return stitch_group
+
def do_contour_underlay(self):
# "contour walk" underlay: do stitches up one side and down the
# other. if the two sides are far away, adding a running stitch to travel
@@ -1196,19 +1354,12 @@ class SatinColumn(EmbroideryElement):
def do_center_walk(self):
# Center walk underlay is just a running stitch down and back on the
# center line between the bezier curves.
+ repeats = self.center_walk_underlay_repeats
- inset_prop = -np.array([self.center_walk_underlay_position, 100-self.center_walk_underlay_position]) / 100
-
- # Do it like contour underlay, but inset all the way to the center.
- pairs = self.plot_points_on_rails(
- self.center_walk_underlay_stitch_tolerance,
- (0, 0), inset_prop)
-
- points = [points[0] for points in pairs]
- stitches = running_stitch.even_running_stitch(points, self.center_walk_underlay_stitch_length, self.center_walk_underlay_stitch_tolerance)
+ stitches = self._get_center_line_stitches()
repeated_stitches = []
- for i in range(self.center_walk_underlay_repeats - 1):
+ for i in range(repeats - 1):
if i % 2 == 0:
repeated_stitches.extend(reversed(stitches))
else:
@@ -1260,6 +1411,17 @@ class SatinColumn(EmbroideryElement):
stitch_group.add_tags(("satin_column", "satin_column_underlay", "satin_zigzag_underlay"))
return stitch_group
+ def _do_top_layer_stitch_group(self, satin):
+ if self.satin_method == 'e_stitch':
+ stitch_group = satin.do_e_stitch()
+ elif self.satin_method == 's_stitch':
+ stitch_group = satin.do_s_stitch()
+ elif self.satin_method == 'zigzag':
+ stitch_group = satin.do_zigzag()
+ else:
+ stitch_group = satin.do_satin()
+ return stitch_group
+
def do_satin(self):
# satin: do a zigzag pattern, alternating between the paths. The
# zigzag looks like this to make the satin stitches look perpendicular
@@ -1410,7 +1572,7 @@ class SatinColumn(EmbroideryElement):
if self._center_walk_is_odd():
stitch_group.stitches = list(reversed(stitch_group.stitches))
- stitch_group.add_tags(("satin", "s_stitch"))
+ stitch_group.add_tags(("satin_column", "s_stitch"))
return stitch_group
def do_zigzag(self):
@@ -1567,51 +1729,121 @@ class SatinColumn(EmbroideryElement):
stitch_group.add_stitch(end_stitch)
def connect_and_add(self, stitch_group, next_stitch_group):
-
+ if not next_stitch_group.stitches:
+ return stitch_group
if stitch_group.stitches:
self.add_running_stitches(stitch_group.stitches[-1], next_stitch_group.stitches[0], stitch_group)
stitch_group += next_stitch_group
return stitch_group
+ @property
+ def start_point(self):
+ return self._get_command_point('starting_point')
+
+ @property
+ def end_point(self):
+ return self._get_command_point('ending_point')
+
+ def _get_command_point(self, command):
+ point = self.get_command(command)
+ if point is not None:
+ point = point.target_point
+ return point
+
+ def _split_satin(self):
+ if self.end_point is not None:
+ satins = self.split(self.end_point)
+ if self.reverse_rails == 'automatic':
+ self._adapt_automatic_rail_swapping(satins)
+ if satins[0] is None:
+ if not self._center_walk_is_odd():
+ satins[1] = satins[1].reverse()
+ if self.swap_rails:
+ satins[1] = satins[1].flip()
+ satins = [None, satins[1]]
+ elif satins[1] is not None:
+ if self._center_walk_is_odd():
+ satins[0] = satins[0].reverse()
+ else:
+ satins[1] = satins[1].reverse()
+ if self.swap_rails:
+ satins[0] = satins[0].flip()
+ else:
+ if self._center_walk_is_odd():
+ satins[0] = satins[0].reverse()
+ satins = [satins[0], None]
+ else:
+ satins = [self, None]
+ return satins
+
+ def _adapt_automatic_rail_swapping(self, satins): # noqa: C901
+ reverse_rails = self._get_rails_to_reverse()
+ if reverse_rails == (False, False):
+ if satins[0] is not None:
+ satins[0].set_param('reverse_rails', 'none')
+ if satins[1] is not None:
+ satins[1].set_param('reverse_rails', 'none')
+ elif reverse_rails == (True, False):
+ if satins[0] is not None:
+ satins[0].set_param('reverse_rails', 'first')
+ if satins[1] is not None:
+ satins[1].set_param('reverse_rails', 'first')
+ elif reverse_rails == (False, True):
+ if satins[0] is not None:
+ satins[0].set_param('reverse_rails', 'second')
+ if satins[1] is not None:
+ satins[1].set_param('reverse_rails', 'second')
+ elif reverse_rails == (True, True):
+ if satins[0] is not None:
+ satins[0].set_param('reverse_rails', 'both')
+ if satins[1] is not None:
+ satins[1].set_param('reverse_rails', 'both')
+
def to_stitch_groups(self, last_stitch_group=None):
# Stitch a variable-width satin column, zig-zagging between two paths.
# The algorithm will draw zigzags between each consecutive pair of
# beziers. The boundary points between beziers serve as "checkpoints",
# allowing the user to control how the zigzags flow around corners.
+ satins = self._split_satin()
+
stitch_group = StitchGroup(
color=self.color,
force_lock_stitches=self.force_lock_stitches,
lock_stitches=self.lock_stitches
)
- if self.center_walk_underlay:
- stitch_group += self.do_center_walk()
+ start_point = self.start_point
+ if start_point is None and last_stitch_group is not None and self.start_at_nearest_point:
+ start_point = nearest_points(shgeo.Point(*last_stitch_group.stitches[-1]), self.center_line)[1]
+ start_point = Point(*list(start_point.coords[0]))
+ if start_point is not None:
+ start_path = self.do_start_path(satins, start_point)
+ stitch_group = self.connect_and_add(stitch_group, start_path)
- if self.contour_underlay:
- contour = self.do_contour_underlay()
- stitch_group = self.connect_and_add(stitch_group, contour)
-
- if self.zigzag_underlay:
- # zigzag underlay comes after contour walk underlay, so that the
- # zigzags sit on the contour walk underlay like rail ties on rails.
- zigzag = self.do_zigzag_underlay()
- stitch_group = self.connect_and_add(stitch_group, zigzag)
+ for i, satin in enumerate(satins):
+ if satin is None:
+ continue
- if self.satin_method == 'e_stitch':
- final_stitch_group = self.do_e_stitch()
- elif self.satin_method == 's_stitch':
- final_stitch_group = self.do_s_stitch()
- elif self.satin_method == 'zigzag':
- final_stitch_group = self.do_zigzag()
- else:
- final_stitch_group = self.do_satin()
+ if i > 0 and None not in satins:
+ end_point_connection = satin.do_end_point_connection()
+ stitch_group = self.connect_and_add(stitch_group, end_point_connection)
- stitch_group = self.connect_and_add(stitch_group, final_stitch_group)
+ stitch_group = self._do_underlay_stitch_groups(i, satin, stitch_group)
+ final_stitch_group = self._do_top_layer_stitch_group(satin)
+ stitch_group = self.connect_and_add(stitch_group, final_stitch_group)
if not stitch_group.stitches:
return []
+ if self.end_point:
+ ending_point_stitch_group = StitchGroup(
+ color=self.color,
+ tags=("satin_column"),
+ stitches=[Point(*self.end_point)]
+ )
+ stitch_group = self.connect_and_add(stitch_group, ending_point_stitch_group)
+
return [stitch_group]
diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py
index c0da08fe..ff9718c5 100644
--- a/lib/elements/stroke.py
+++ b/lib/elements/stroke.py
@@ -515,7 +515,7 @@ class Stroke(EmbroideryElement):
return coords
def get_ripple_target(self):
- command = self.get_command('ripple_target')
+ command = self.get_command('target_point')
if command:
pos = [float(command.use.get("x", 0)), float(command.use.get("y", 0))]
transform = get_node_transform(command.use)
diff --git a/lib/extensions/auto_run.py b/lib/extensions/auto_run.py
index 02997fd0..3b2003e4 100644
--- a/lib/extensions/auto_run.py
+++ b/lib/extensions/auto_run.py
@@ -35,10 +35,10 @@ class AutoRun(CommandsExtension):
autorun(elements, self.options.preserve_order, break_up, starting_point, ending_point, self.options.trim)
def get_starting_point(self):
- return self.get_command_point("run_start")
+ return self.get_command_point("autoroute_start")
def get_ending_point(self):
- return self.get_command_point("run_end")
+ return self.get_command_point("autoroute_end")
def get_command_point(self, command_type):
command = None
diff --git a/lib/extensions/auto_satin.py b/lib/extensions/auto_satin.py
index 8536e4ee..d5456bcb 100644
--- a/lib/extensions/auto_satin.py
+++ b/lib/extensions/auto_satin.py
@@ -22,10 +22,10 @@ class AutoSatin(CommandsExtension):
self.arg_parser.add_argument("-p", "--preserve_order", dest="preserve_order", type=inkex.Boolean, default=False)
def get_starting_point(self):
- return self.get_point("satin_start")
+ return self.get_point("autoroute_start")
def get_ending_point(self):
- return self.get_point("satin_end")
+ return self.get_point("autoroute_end")
def get_point(self, command_type):
command = None
diff --git a/lib/extensions/cut_satin.py b/lib/extensions/cut_satin.py
index a2c4f504..132c727f 100644
--- a/lib/extensions/cut_satin.py
+++ b/lib/extensions/cut_satin.py
@@ -39,6 +39,8 @@ class CutSatin(InkstitchExtension):
command.connector.getparent().remove(command.connector)
new_satins = satin.split(split_point)
+ if None in new_satins:
+ continue
transform = get_correction_transform(satin.node)
parent = satin.node.getparent()
index = parent.index(satin.node)
diff --git a/lib/extensions/gradient_blocks.py b/lib/extensions/gradient_blocks.py
index 68e1e8e9..b87e5f9e 100644
--- a/lib/extensions/gradient_blocks.py
+++ b/lib/extensions/gradient_blocks.py
@@ -26,7 +26,7 @@ class GradientBlocks(CommandsExtension):
This will break apart fill objects with a gradient fill into solid color blocks with end_row_spacing.
'''
- COMMANDS = ['fill_start', 'fill_end']
+ COMMANDS = ['starting_point', 'ending_point']
def __init__(self, *args, **kwargs):
CommandsExtension.__init__(self, *args, **kwargs)
@@ -112,8 +112,8 @@ class GradientBlocks(CommandsExtension):
nearest = nearest_points(current.shape, previous.shape)
pos_current = self._get_command_postion(current, nearest[0])
pos_previous = self._get_command_postion(previous, nearest[1])
- add_commands(current, ['fill_end'], pos_current)
- add_commands(previous, ['fill_start'], pos_previous)
+ add_commands(current, ['ending_point'], pos_current)
+ add_commands(previous, ['starting_point'], pos_previous)
def _get_command_postion(self, fill, point):
center = fill.shape.centroid
diff --git a/lib/extensions/redwork.py b/lib/extensions/redwork.py
index 7bc237e9..9ad2aca5 100644
--- a/lib/extensions/redwork.py
+++ b/lib/extensions/redwork.py
@@ -47,10 +47,10 @@ class Redwork(InkstitchExtension):
self.merge_distance = self.options.merge_distance * PIXELS_PER_MM
self.minimum_path_length = self.options.minimum_path_length * PIXELS_PER_MM
- starting_point = self._get_starting_point('run_start')
+ starting_point = self._get_starting_point('autoroute_start')
# as the resulting path starts and ends at same place we can also use ending point
if not starting_point:
- starting_point = self._get_starting_point('run_end')
+ starting_point = self._get_starting_point('autoroute_end')
multi_line_string = self._elements_to_multi_line_string(elements)
if starting_point:
diff --git a/lib/svg/path.py b/lib/svg/path.py
index 9d92058b..548a82f2 100644
--- a/lib/svg/path.py
+++ b/lib/svg/path.py
@@ -87,6 +87,9 @@ def line_strings_to_csp(line_strings):
except AttributeError:
pass
+ if line_strings is None:
+ return None
+
return point_lists_to_csp(ls.coords for ls in line_strings)
diff --git a/lib/svg/tags.py b/lib/svg/tags.py
index b8f04ef2..5afb2064 100644
--- a/lib/svg/tags.py
+++ b/lib/svg/tags.py
@@ -167,6 +167,8 @@ inkstitch_attribs = [
'random_split_phase',
'random_split_jitter_percent',
'min_random_split_length_mm',
+ 'running_stitch_position',
+ 'start_at_nearest_point',
# stitch_plan
'invisible_layers',
'layer_visibility',
diff --git a/lib/tartan/svg.py b/lib/tartan/svg.py
index 0fd8b579..15646629 100644
--- a/lib/tartan/svg.py
+++ b/lib/tartan/svg.py
@@ -166,11 +166,11 @@ class TartanSvgGroup:
end = element.get('inkstitch:end')
if start:
start = start[1:-1].split(',')
- add_commands(fill, ['fill_start'], self._get_command_position(fill, (float(start[0]), float(start[1]))))
+ add_commands(fill, ['starting_point'], self._get_command_position(fill, (float(start[0]), float(start[1]))))
element.pop('inkstitch:start')
if end:
end = end[1:-1].split(',')
- add_commands(fill, ['fill_end'], self._get_command_position(fill, (float(end[0]), float(end[1]))))
+ add_commands(fill, ['ending_point'], self._get_command_position(fill, (float(end[0]), float(end[1]))))
element.pop('inkstitch:end')
def _route_shapes(self, routing_lines: defaultdict, outline_shape: MultiPolygon, shapes: defaultdict, weft: bool = False) -> defaultdict:
diff --git a/lib/update.py b/lib/update.py
index 5b092a8f..05d84272 100644
--- a/lib/update.py
+++ b/lib/update.py
@@ -5,6 +5,7 @@
from inkex import errormsg
+from .commands import ensure_symbol
from .elements import EmbroideryElement
from .gui.request_update_svg_version import RequestUpdate
from .i18n import _
@@ -12,7 +13,7 @@ from .metadata import InkStitchMetadata
from .svg import PIXELS_PER_MM
from .svg.tags import EMBROIDERABLE_TAGS, INKSTITCH_ATTRIBS
-INKSTITCH_SVG_VERSION = 2
+INKSTITCH_SVG_VERSION = 3
def update_inkstitch_document(svg, selection=None):
@@ -68,6 +69,8 @@ def automatic_version_update(document, file_version, INKSTITCH_SVG_VERSION):
for element in document.iterdescendants():
if element.tag in EMBROIDERABLE_TAGS:
update_legacy_params(EmbroideryElement(element), file_version, INKSTITCH_SVG_VERSION)
+ if file_version < 3:
+ update_legacy_commands(document)
def _update_inkstitch_svg_version(svg):
@@ -173,3 +176,40 @@ def _replace_legacy_embroider_param(element, param):
value = element.node.get(param, "").strip()
element.set_param(param[10:], value)
del element.node.attrib[param]
+
+
+'''
+Update legacy commands
+======================
+'''
+
+
+def update_legacy_commands(document):
+ '''
+ Changes for svg version 3
+ '''
+ search_string = "//svg:symbol"
+ symbols = document.xpath(search_string)
+ for symbol in symbols:
+ _rename_command(document, symbol, 'inkstitch_fill_start', 'starting_point')
+ _rename_command(document, symbol, 'inkstitch_fill_end', 'ending_point')
+ _rename_command(document, symbol, 'inkstitch_satin_start', 'autoroute_start')
+ _rename_command(document, symbol, 'inkstitch_satin_end', 'autoroute_end')
+ _rename_command(document, symbol, 'inkstitch_run_start', 'autoroute_start')
+ _rename_command(document, symbol, 'inkstitch_run_end', 'autoroute_end')
+ _rename_command(document, symbol, 'inkstitch_ripple_target', 'target_point')
+
+
+def _rename_command(document, symbol, old_name, new_name):
+ symbol_id = symbol.get_id()
+ if symbol_id.startswith(old_name):
+ symbol.getparent().remove(symbol)
+ ensure_symbol(document, new_name)
+ _update_command(document, symbol_id, new_name)
+
+
+def _update_command(document, old_id, new_name):
+ xpath2 = f"//svg:use[@xlink:href='#{old_id}']"
+ elements = document.xpath(xpath2)
+ for element in elements:
+ element.set('xlink:href', f'#inkstitch_{new_name}')
diff --git a/symbols/inkstitch.svg b/symbols/inkstitch.svg
index 2a80a052..137d68f1 100644
--- a/symbols/inkstitch.svg
+++ b/symbols/inkstitch.svg
@@ -59,9 +59,9 @@
+ id="inkstitch_ending_point">
Fill stitch ending point
+ id="inkstitch_title9427">Ending point
+ id="inkstitch_starting_point">
Fill stitch starting point
+ id="inkstitch_title9432">Starting point
- Satin column starting point
-
-
-
-
-
- Satin column ending point
-
-
-
-
-
Running stitch starting point
@@ -311,7 +269,7 @@
d="M -3.8159516,-5.6184574 c -0.3237427,0.020819 -0.5868063,0.2896236 -0.5907925,0.6167873 -0.00301,0.2444103 0.1384108,0.4575508 0.3447536,0.5613983 l -0.084402,6.772037 c -0.1244867,-0.03501 -0.2442949,-0.092709 -0.3519231,-0.1734001 -0.018852,-0.014824 -0.04551,-0.014824 -0.064361,0 -0.018491,0.013861 -0.025495,0.038228 -0.017164,0.05968 l 0.6437207,1.8106215 c 0.016803,0.044746 0.080472,0.044746 0.097275,0 l 0.6923582,-1.7949729 c 0.01924,-0.049558 -0.04036,-0.092132 -0.081524,-0.058277 -0.1120849,0.077886 -0.2339971,0.131597 -0.3605046,0.1634443 l 0.078701,-6.7706068 c 0.2092494,-0.097934 0.3546084,-0.3086274 0.3576257,-0.5542753 0.00418,-0.34328 -0.2710359,-0.6282831 -0.6165645,-0.632436 -0.016194,-1.924e-4 -0.031281,-0.00102 -0.047198,-3e-7 z m 0.9498575,1.1369602 c -0.042382,0.00503 -0.060846,0.055939 -0.031474,0.086686 l 1.2703061,1.4510604 c 0.035433,0.033525 0.093621,0.00416 0.087254,-0.044058 -0.016443,-0.1368774 -0.00712,-0.2718022 0.025745,-0.3993565 l 5.8279214,3.19201934 c -0.00955,0.23010929 0.1105352,0.45752327 0.3261511,0.57558932 0.3026489,0.1656996 0.6815068,0.0590468 0.8482917,-0.24160502 0.1667849,-0.30067931 0.059461,-0.68276459 -0.2431877,-0.84846414 -0.216862,-0.11872613 -0.4758284,-0.0980447 -0.6666138,0.0341025 l -5.8250435,-3.1905893 c 0.090438,-0.093452 0.1986471,-0.1708699 0.32186037,-0.2274139 0.044292,-0.022937 0.033578,-0.088721 -0.015724,-0.096642 L -2.8489315,-4.4800672 c -0.00556,-0.00146 -0.011405,-0.00189 -0.017162,-0.00146 z m 6.9651605,5.10354566 -1.909736,0.3126702 c -0.047392,0.011523 -0.054063,0.075768 -0.01,0.096642 0.1244589,0.057067 0.2344955,0.1342923 0.3261511,0.2273865 L -3.4211257,4.5999927 C -3.6139873,4.4704034 -3.8733966,4.4493919 -4.0877673,4.5701537 -4.38834,4.7394835 -4.4899335,5.1199736 -4.3194944,5.4186179 c 0.170439,0.2986167 0.5534215,0.4066446 0.8540219,0.2373147 0.2139276,-0.1204863 0.3297497,-0.3481203 0.3175695,-0.5769918 L 2.778711,1.7376949 c 0.03333,0.1260415 0.043323,0.2590963 0.027184,0.3936635 -0.00791,0.053024 0.060763,0.081379 0.092985,0.038365 L 4.1477039,0.70304186 c 0.026048,-0.036523 -0.00388,-0.086439 -0.048637,-0.0809934 Z" />
Running stitch ending point
@@ -325,10 +283,10 @@
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" />
Ripple stitch target point
+ id="inkstitch_title9427-9">Target point
Create symbols carefully! They must be centered about the origin before being converted to a symbol.
-
-