From 422e770eadd1805601861632845b3e63c66c5acc Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 30 Jun 2018 14:16:47 -0400 Subject: add stop and trim command symbols --- symbols/inkstitch.svg | 72 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/symbols/inkstitch.svg b/symbols/inkstitch.svg index 2af52d92..9c551964 100644 --- a/symbols/inkstitch.svg +++ b/symbols/inkstitch.svg @@ -24,9 +24,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="2" - inkscape:cx="64.500275" - inkscape:cy="322.07765" + inkscape:zoom="4" + inkscape:cx="127.82066" + inkscape:cy="323.33371" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -90,6 +90,48 @@ inkscape:transform-center-x="-1.7419043" style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.74180555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + + Stop the machine after sewing this object (for applique, etc) + + + + + + Trim the thread after sewing this object. + + + @@ -123,5 +165,29 @@ y="0" width="100%" height="100%" /> + + + -- cgit v1.2.3 From 61983b615b202bb95c21d7a5021af3373615e839 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 30 Jun 2018 14:16:56 -0400 Subject: add has_command() --- lib/elements/element.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/elements/element.py b/lib/elements/element.py index 3c31f1b0..f0b7ea6f 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -214,6 +214,10 @@ class EmbroideryElement(object): def get_commands(self, command): return [c for c in self.commands if c.command == command] + @cache + def has_command(self, command): + return len(self.get_commands(command)) > 0 + @cache def get_command(self, command): commands = self.get_commands(command) -- cgit v1.2.3 From 3893d13b52b2755ea134ec4d3a215ee807dbbc2e Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 30 Jun 2018 14:18:45 -0400 Subject: add support for trim/stop commands --- lib/elements/element.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/elements/element.py b/lib/elements/element.py index f0b7ea6f..1c67d123 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -268,8 +268,8 @@ class EmbroideryElement(object): patches = self.to_patches(last_patch) if patches: - patches[-1].trim_after = self.trim_after - patches[-1].stop_after = self.stop_after + patches[-1].trim_after = self.has_command("trim") or self.trim_after + patches[-1].stop_after = self.has_command("stop") or self.stop_after return patches -- cgit v1.2.3 From aa86dc56ad5cb9166ab1c9cda036d9521855ad29 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 30 Jun 2018 14:19:28 -0400 Subject: remove 'TRIM after' and 'STOP after' from Params dialog --- lib/elements/element.py | 12 ------------ messages.po | 16 +--------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/lib/elements/element.py b/lib/elements/element.py index 1c67d123..62e9745d 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -242,22 +242,10 @@ class EmbroideryElement(object): return [self.strip_control_points(subpath) for subpath in path] @property - @param('trim_after', - _('TRIM after'), - tooltip=_('Trim thread after this object (for supported machines and file formats)'), - type='boolean', - default=False, - sort_index=1000) def trim_after(self): return self.get_boolean_param('trim_after', False) @property - @param('stop_after', - _('STOP after'), - tooltip=_('Add STOP instruction after this object (for supported machines and file formats)'), - type='boolean', - default=False, - sort_index=1000) def stop_after(self): return self.get_boolean_param('stop_after', False) diff --git a/messages.po b/messages.po index 4607abeb..621db2e3 100644 --- a/messages.po +++ b/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2018-07-12 20:04-0400\n" +"POT-Creation-Date: 2018-07-12 20:13-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -51,20 +51,6 @@ msgstr "" msgid "%(id)s has more than one command of type '%(command)s' linked to it" msgstr "" -msgid "TRIM after" -msgstr "" - -msgid "Trim thread after this object (for supported machines and file formats)" -msgstr "" - -msgid "STOP after" -msgstr "" - -msgid "" -"Add STOP instruction after this object (for supported machines and file " -"formats)" -msgstr "" - msgid "Fill" msgstr "" -- cgit v1.2.3 From c0a04f3dca01fc6ccdc398e8c54fff67383f760d Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Mon, 2 Jul 2018 21:07:31 -0400 Subject: center symbols on the origin --- symbols/inkstitch.svg | 154 ++++++++++++++++++++++++-------------------------- 1 file changed, 75 insertions(+), 79 deletions(-) diff --git a/symbols/inkstitch.svg b/symbols/inkstitch.svg index 9c551964..db8813b6 100644 --- a/symbols/inkstitch.svg +++ b/symbols/inkstitch.svg @@ -18,6 +18,7 @@ inkscape:version="0.92.3 (unknown)" sodipodi:docname="inkstitch.svg"> + inkscape:snap-global="true" + showguides="false" + inkscape:snap-others="true" + inkscape:object-nodes="false" + inkscape:snap-nodes="false"> + id="inkstitch_stop"> Fill stitch starting point - Stop the machine after sewing this object (for applique, etc) + + d="m 9.246554,58.4095 c -1.9e-6,5.106729 -4.1398241,9.24655 -9.246553,9.24655 -5.1067293,0 -9.2465521,-4.139821 -9.246554,-9.24655 1e-7,-2.452338 0.9741879,-4.804235 2.7082531,-6.538301 1.7340653,-1.734065 4.0859624,-2.708252 6.5383009,-2.708252 5.1067301,0 9.2465528,4.139823 9.246553,9.246553 0,0 0,0 0,0" + id="circle13330" + inkscape:connector-curvature="0" /> + style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60622311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:4.81866985, 4.81866985;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" + d="m -3.168998,53.75983 c 0,0 2.515878,0 2.515878,0 0,0 0,9.14087 0,9.14087 0,0 -2.515878,0 -2.515878,0 0,0 0,-9.14087 0,-9.14087" + id="path13332" + inkscape:connector-curvature="0" /> + Fill stitch ending point - Fill stitch starting point + + d="M 9.246554,58.4095 C 9.2465521,63.516229 5.1067293,67.65605 0,67.65605 c -5.1067289,0 -9.2465511,-4.139821 -9.246553,-9.24655 2e-7,-5.10673 4.1398229,-9.246553 9.246553,-9.246553 2.4523385,0 4.8042356,0.974187 6.5383009,2.708252 1.7340652,1.734066 2.708253,4.085963 2.7082531,6.538301 0,0 0,0 0,0" + id="circle13166-6" /> + id="inkstitch_trim"> Stop the machine after sewing this object (for applique, etc) - + id="title9282">Trim the thread after sewing this object. + 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" + d="m 9.07045,57.915929 c 1.8e-6,2.452339 -0.9741847,4.804237 -2.7082493,6.538304 -1.7340645,1.734066 -4.0859617,2.708255 -6.5383007,2.708256 -2.4523407,2e-6 -4.8042405,-0.974186 -6.5383072,-2.708253 -1.7340668,-1.734067 -2.7082546,-4.085966 -2.7082528,-6.538307 6e-7,-2.452339 0.9741895,-4.804237 2.708256,-6.538301 1.7340665,-1.734065 4.0859648,-2.708252 6.538304,-2.70825 5.1067282,2e-6 9.2465487,4.139823 9.24655,9.246551 0,0 0,0 0,0" + id="circle13405" + inkscape:connector-curvature="0" /> + id="path13416" + d="m -3,52.426099 c -1.30575,0 -2.375,1.06924 -2.375,2.375 0,1.30575 1.06925,2.375 2.375,2.375 0.58687,0 1.11944,-0.22369 1.53516,-0.58007 0,0 0.61718,1.62109 0.61718,1.62109 0,0 -2.29882,6.01758 -2.29882,6.01758 0.98655,-0.12511 1.23728,-0.26171 1.67382,-0.97461 0,0 1.33008,-3.18945 1.33008,-3.18945 0,0 1.23633,3.25 1.23633,3.25 0.23227,0.77906 0.84315,0.79218 1.57813,1.07226 0,0 -2.05469,-6.14258 -2.05469,-6.14258 0,0 0.73047,-1.75 0.73047,-1.75 0.42849,0.41682 1.01136,0.67578 1.65234,0.67578 1.30575,0 2.375,-1.06925 2.375,-2.375 0,-1.30576 -1.06925,-2.375 -2.375,-2.375 -1.06233,0 -1.95701,0.71265 -2.25781,1.67969 0,0 -0.0117,-0.0156 -0.0117,-0.0156 0,0 -0.80274,2.10156 -0.80274,2.10156 0,0 -0.59179,-1.76562 -0.59179,-1.76562 -0.18242,-1.12808 -1.15865,-2 -2.33594,-2 0,0 -2e-5,-3e-5 -2e-5,-3e-5 m 0,1 c 0.76531,0 1.375,0.60968 1.375,1.375 0,0.76531 -0.60969,1.375 -1.375,1.375 -0.76531,0 -1.375,-0.60969 -1.375,-1.375 0,-0.76532 0.60969,-1.375 1.375,-1.375 0,0 0,0 0,0 m 6,0 c 0.76531,0 1.375,0.60968 1.375,1.375 0,0.76531 -0.60969,1.375 -1.375,1.375 -0.76531,0 -1.375,-0.60969 -1.375,-1.375 0,-0.76532 0.60969,-1.375 1.375,-1.375 0,0 0,0 0,0" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.41421342;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + inkscape:connector-curvature="0" /> + id="inkstitch_fill_end"> Trim the thread after sewing this object. - + id="title9427">Fill stitch ending point + 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" + d="m 9.260977,58.431186 c -1.9e-6,5.106729 -4.1398241,9.24655 -9.246553,9.24655 -5.1067293,0 -9.2465521,-4.139821 -9.246554,-9.24655 10e-8,-2.452338 0.9741879,-4.804235 2.7082531,-6.538301 1.7340653,-1.734065 4.0859624,-2.708252 6.5383009,-2.708252 5.1067301,0 9.2465528,4.139823 9.246553,9.246553 0,0 0,0 0,0" + id="circle13166" /> + - Create symbols carefully! They must be centered about the origin before being converted to a symbol. + height="100%" + transform="translate(151.18108,-1.7165886)" /> - + transform="translate(113.3858,-1.7165886)" /> + transform="translate(75.590552,-1.7165891)" /> + height="100%" + transform="translate(37.780826,-1.7382746)" /> -- cgit v1.2.3 From a0659e2c2d7609294c1a5a70153b1aa647595e94 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:15:49 -0400 Subject: remove leftover debugging code (oops) --- lib/commands.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/commands.py b/lib/commands.py index ec62d716..02c13b25 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -77,9 +77,6 @@ def find_commands(node): try: commands.append(Command(connector)) except ValueError: - import sys - import traceback - print >> sys.stderr, "not a Command:", connector.get('id'), traceback.format_exc() # Parsing the connector failed, meaning it's not actually an Ink/Stitch command. pass -- cgit v1.2.3 From d090fa003830f117918fac201ca527d513507a70 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:16:49 -0400 Subject: move get_bundled_dir to utils --- lib/extensions/install.py | 10 ++-------- lib/utils/__init__.py | 1 + lib/utils/paths.py | 10 ++++++++++ 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 lib/utils/paths.py diff --git a/lib/extensions/install.py b/lib/extensions/install.py index d55b96d0..42a92113 100644 --- a/lib/extensions/install.py +++ b/lib/extensions/install.py @@ -13,7 +13,7 @@ import logging import wx import inkex -from ..utils import guess_inkscape_config_path +from ..utils import guess_inkscape_config_path, get_bundled_dir class InstallerFrame(wx.Frame): @@ -78,15 +78,9 @@ class InstallerFrame(wx.Frame): def install_addons(self, type): path = os.path.join(self.path, type) - src_dir = self.get_bundled_dir(type) + src_dir = get_bundled_dir(type) self.copy_files(glob(os.path.join(src_dir, "*")), path) - def get_bundled_dir(self, name): - if getattr(sys, 'frozen', None) is not None: - return realpath(os.path.join(sys._MEIPASS, '..', name)) - else: - return realpath(os.path.join(dirname(realpath(__file__)), '..', '..', name)) - if (sys.platform == "win32"): # If we try to just use shutil.copy it says the operation requires elevation. def copy_files(self, files, dest): diff --git a/lib/utils/__init__.py b/lib/utils/__init__.py index ff06d4a9..78d037f1 100644 --- a/lib/utils/__init__.py +++ b/lib/utils/__init__.py @@ -2,3 +2,4 @@ from geometry import * from cache import cache from io import * from inkscape import * +from paths import * diff --git a/lib/utils/paths.py b/lib/utils/paths.py new file mode 100644 index 00000000..863e8e69 --- /dev/null +++ b/lib/utils/paths.py @@ -0,0 +1,10 @@ +import sys +import os +from os.path import dirname, realpath + + +def get_bundled_dir(name): + if getattr(sys, 'frozen', None) is not None: + return realpath(os.path.join(sys._MEIPASS, "..", name)) + else: + return realpath(os.path.join(dirname(realpath(__file__)), '..', '..', name)) -- cgit v1.2.3 From 62ef2850a2f57d64d0e65fbfc055b85e3c940031 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:17:20 -0400 Subject: generalize Element.shape and implement in all element types --- lib/elements/element.py | 4 ++++ lib/elements/polyline.py | 7 +++++++ lib/elements/satin_column.py | 11 +++++++++++ lib/elements/stroke.py | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/lib/elements/element.py b/lib/elements/element.py index 62e9745d..ebca90a4 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -205,6 +205,10 @@ class EmbroideryElement(object): def parse_path(self): return apply_transforms(self.path, self.node) + @property + def shape(self): + raise NotImplementedError("INTERNAL ERROR: %s must implement shape()", self.__class__) + @property @cache def commands(self): diff --git a/lib/elements/polyline.py b/lib/elements/polyline.py index 5c474237..b9ffdc0b 100644 --- a/lib/elements/polyline.py +++ b/lib/elements/polyline.py @@ -1,3 +1,5 @@ +from shapely import geometry as shgeo + from .element import param, EmbroideryElement, Patch from ..i18n import _ from ..utils.geometry import Point @@ -27,6 +29,11 @@ class Polyline(EmbroideryElement): return points + @property + @cache + def shape(self): + return shgeo.LineString(self.points) + @property def path(self): # A polyline is a series of connected line segments described by their diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 1d13c5e0..2ceb38de 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -87,6 +87,17 @@ class SatinColumn(EmbroideryElement): # the edges of the satin column. return self.get_float_param("zigzag_underlay_inset_mm") or self.contour_underlay_inset / 2.0 + @property + @cache + def shape(self): + # This isn't used for satins at all, but other parts of the code + # may need to know the general shape of a satin column. + + flattened = self.flatten(self.parse_path()) + line_strings = [shgeo.LineString(path) for path in flattened] + + return shgeo.MultiLineString(line_strings) + @property @cache def csp(self): diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index eca9e0ba..e8eb4783 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -1,4 +1,5 @@ import sys +import shapely.geometry from .element import param, EmbroideryElement, Patch from ..i18n import _ @@ -50,6 +51,12 @@ class Stroke(EmbroideryElement): else: return self.flatten(path) + @property + @cache + def shape(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) def manual_stitch_mode(self): -- cgit v1.2.3 From 22102ee0e839b22668873c45756a3666d4d9cbff Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:42:53 -0400 Subject: add CONNECTION_TYPE --- lib/svg/tags.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/svg/tags.py b/lib/svg/tags.py index 5488608c..7eb87540 100644 --- a/lib/svg/tags.py +++ b/lib/svg/tags.py @@ -12,6 +12,7 @@ INKSCAPE_LABEL = inkex.addNS('label', 'inkscape') INKSCAPE_GROUPMODE = inkex.addNS('groupmode', 'inkscape') CONNECTION_START = inkex.addNS('connection-start', 'inkscape') CONNECTION_END = inkex.addNS('connection-end', 'inkscape') +CONNECTOR_TYPE = inkex.addNS('connector-type', 'inkscape') XLINK_HREF = inkex.addNS('href', 'xlink') EMBROIDERABLE_TAGS = (SVG_PATH_TAG, SVG_POLYLINE_TAG) -- cgit v1.2.3 From d9033be6fc4dcca4ee33f80a55f1ae4a7921be89 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:44:08 -0400 Subject: refactor out logic to gather node's transforms --- lib/svg/__init__.py | 2 +- lib/svg/path.py | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/svg/__init__.py b/lib/svg/__init__.py index 50543b1b..8e846555 100644 --- a/lib/svg/__init__.py +++ b/lib/svg/__init__.py @@ -1,3 +1,3 @@ from .svg import color_block_to_point_lists, render_stitch_plan from .units import * -from .path import apply_transforms +from .path import apply_transforms, get_node_transform diff --git a/lib/svg/path.py b/lib/svg/path.py index a8012774..2d9c0ff3 100644 --- a/lib/svg/path.py +++ b/lib/svg/path.py @@ -4,6 +4,14 @@ import cubicsuperpath from .units import get_viewbox_transform def apply_transforms(path, node): + transform = get_node_transform(node) + + # apply the combined transform to this node's path + simpletransform.applyTransformToPath(transform, path) + + return path + +def get_node_transform(node): # start with the identity transform transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] @@ -14,7 +22,4 @@ def apply_transforms(path, node): viewbox_transform = get_viewbox_transform(node.getroottree().getroot()) transform = simpletransform.composeTransform(viewbox_transform, transform) - # apply the combined transform to this node's path - simpletransform.applyTransformToPath(transform, path) - - return path + return transform -- cgit v1.2.3 From 0d41f8685c4bae261ef11d9795de63567e335c19 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:44:56 -0400 Subject: fixup! center symbols on the origin --- symbols/inkstitch.svg | 144 +++++++++++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/symbols/inkstitch.svg b/symbols/inkstitch.svg index db8813b6..a9c3bf17 100644 --- a/symbols/inkstitch.svg +++ b/symbols/inkstitch.svg @@ -26,8 +26,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="4" - inkscape:cx="56.98931" - inkscape:cy="305.83326" + inkscape:cx="30.48931" + inkscape:cy="293.08326" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -45,37 +45,47 @@ inkscape:object-nodes="false" inkscape:snap-nodes="false"> + units="mm" + spacingx="18.897638" + spacingy="18.897638" + color="#f03fff" + opacity="0.1254902" + empspacing="2" /> Ink/Stitch Commands + id="inkstitch_fill_end"> Stop the machine after sewing this object (for applique, etc) + id="title9427">Fill stitch ending point + + + Trim the thread after sewing this object. + Fill stitch starting point + inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" /> + id="inkstitch_stop"> Trim the thread after sewing this object. + id="title13328">Stop the machine after sewing this object (for applique, etc) - - - Fill stitch ending point - + id="path13333" + d="m 0.83097287,-4.6497026 c 0,0 2.51588003,0 2.51588003,0 0,0 0,9.14087 0,9.14087 0,0 -2.51588003,0 -2.51588003,0 0,0 0,-9.14087 0,-9.14087" + style="display:inline;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60622311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:4.81866985, 4.81866985;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" + inkscape:connector-curvature="0" /> + id="layer1" + style="display:inline"> Create symbols carefully! They must be centered about the origin before being converted to a symbol. Create symbols carefully! They must be centered about the origin before being converted to a symbol. + transform="translate(37.82169,75.511319)" /> + transform="translate(75.590552,75.590552)" /> + transform="translate(113.38583,75.590552)" /> + transform="translate(151.1811,75.590552)" /> -- cgit v1.2.3 From 3de394e14b00ac2653084f534149db418bd6cebd Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:45:21 -0400 Subject: add new extension to attach commands to objects --- inx/inkstitch_commands.inx | 21 ++++++++ lib/extensions/__init__.py | 1 + lib/extensions/commands.py | 128 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 inx/inkstitch_commands.inx create mode 100644 lib/extensions/commands.py diff --git a/inx/inkstitch_commands.inx b/inx/inkstitch_commands.inx new file mode 100644 index 00000000..7b42ca0e --- /dev/null +++ b/inx/inkstitch_commands.inx @@ -0,0 +1,21 @@ + + + <_name>Attach Commands + org.inkstitch.commands + inkstitch.py + inkex.py + false + false + false + false + commands + + all + + + + + + diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index b11ba1a4..dfdc7a3e 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -7,3 +7,4 @@ from input import Input from output import Output from zip import Zip from flip import Flip +from commands import * diff --git a/lib/extensions/commands.py b/lib/extensions/commands.py new file mode 100644 index 00000000..26ced110 --- /dev/null +++ b/lib/extensions/commands.py @@ -0,0 +1,128 @@ +import os +import sys +import inkex +import simpletransform +import cubicsuperpath +from copy import deepcopy +from shapely import geometry as shgeo + +from .base import InkstitchExtension +from ..i18n import _ +from ..elements import SatinColumn +from ..utils import get_bundled_dir, cache +from ..svg.tags import SVG_DEFS_TAG, SVG_GROUP_TAG, SVG_USE_TAG, SVG_PATH_TAG, INKSCAPE_GROUPMODE, XLINK_HREF, CONNECTION_START, CONNECTION_END, CONNECTOR_TYPE +from ..svg import get_node_transform + + +class Commands(InkstitchExtension): + COMMANDS = ["fill_start", "fill_end", "stop", "trim"] + + def __init__(self, *args, **kwargs): + InkstitchExtension.__init__(self, *args, **kwargs) + for command in self.COMMANDS: + self.OptionParser.add_option("--%s" % command, type="inkbool") + + @property + def symbols_path(self): + return os.path.join(get_bundled_dir("symbols"), "inkstitch.svg") + + @property + @cache + def symbols_svg(self): + with open(self.symbols_path) as symbols_file: + return inkex.etree.parse(symbols_file) + + @property + @cache + def symbol_defs(self): + return self.symbols_svg.find(SVG_DEFS_TAG) + + @property + @cache + def defs(self): + return self.document.find(SVG_DEFS_TAG) + + def ensure_symbol(self, command): + path = "./*[@id='inkstitch_%s']" % command + if self.defs.find(path) is None: + self.defs.append(deepcopy(self.symbol_defs.find(path))) + + def get_correction_transform(self, node): + # if we want to place our new nodes in the same group as this node, + # then we'll need to factor in the effects of any transforms set on + # the parents of this node. + + # we can ignore the transform on the node itself since it won't apply + # to the objects we add + transform = get_node_transform(node.getparent()) + + # now invert it, so that we can position our objects in absolute + # coordinates + transform = simpletransform.invertTransform(transform) + + return simpletransform.formatTransform(transform) + + def add_connector(self, symbol, element): + # I'd like it if I could position the connector endpoint nicely but inkscape just + # moves it to the element's center immediately after the extension runs. + start_pos = (symbol.get('x'), symbol.get('y')) + end_pos = element.shape.centroid + + path = inkex.etree.Element(SVG_PATH_TAG, + { + "id": self.uniqueId("connector"), + "d": "M %s,%s %s,%s" % (start_pos[0], start_pos[1], end_pos.x, end_pos.y), + "style": "stroke:#000000;stroke-width:1px;", + "transform": self.get_correction_transform(symbol), + CONNECTION_START: "#%s" % symbol.get('id'), + CONNECTION_END: "#%s" % element.node.get('id'), + CONNECTOR_TYPE: "polyline", + } + ) + + symbol.getparent().insert(symbol.getparent().index(symbol), path) + + def get_command_pos(self, element, index, total): + # Put command symbols 30 pixels out from the shape, spaced evenly around it. + outline = element.shape.buffer(30).exterior + return outline.interpolate(index / float(total), normalized=True) + + def add_command(self, element, commands): + for i, command in enumerate(commands): + pos = self.get_command_pos(element, i, len(commands)) + + symbol = inkex.etree.SubElement(element.node.getparent(), SVG_USE_TAG, + { + "id": self.uniqueId("use"), + XLINK_HREF: "#inkstitch_%s" % command, + "height": "100%", + "width": "100%", + "x": str(pos.x), + "y": str(pos.y), + "transform": self.get_correction_transform(element.node) + } + ) + + self.add_connector(symbol, element) + + def effect(self): + if not self.get_elements(): + return + + if not self.selected: + inkex.errormsg(_("Please select one or more objects to which to attach commands.")) + return + + self.svg = self.document.getroot() + + commands = [command for command in self.COMMANDS if getattr(self.options, command)] + + if not commands: + inkex.errormsg(_("Please choose one or more commands to attach.")) + return + + for command in commands: + self.ensure_symbol(command) + + for element in self.elements: + self.add_command(element, commands) -- cgit v1.2.3 From 1c5e4fbf73e673a12d67d27a1f0e88c2265c762f Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 21:54:23 -0400 Subject: set fill to none for connectors --- lib/extensions/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/extensions/commands.py b/lib/extensions/commands.py index 26ced110..aeda2cc2 100644 --- a/lib/extensions/commands.py +++ b/lib/extensions/commands.py @@ -72,7 +72,7 @@ class Commands(InkstitchExtension): { "id": self.uniqueId("connector"), "d": "M %s,%s %s,%s" % (start_pos[0], start_pos[1], end_pos.x, end_pos.y), - "style": "stroke:#000000;stroke-width:1px;", + "style": "stroke:#000000;stroke-width:1px;fill:none;", "transform": self.get_correction_transform(symbol), CONNECTION_START: "#%s" % symbol.get('id'), CONNECTION_END: "#%s" % element.node.get('id'), -- cgit v1.2.3 From 7ccc6aa72ce02ea335f129577c8984698a987d0e Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 22:08:08 -0400 Subject: remove legacy params when attaching the equivalent command --- lib/extensions/commands.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/extensions/commands.py b/lib/extensions/commands.py index aeda2cc2..9c080b4e 100644 --- a/lib/extensions/commands.py +++ b/lib/extensions/commands.py @@ -87,8 +87,26 @@ class Commands(InkstitchExtension): outline = element.shape.buffer(30).exterior return outline.interpolate(index / float(total), normalized=True) + def remove_legacy_param(self, element, command): + if command == "trim" or command == "stop": + # If they had the old "TRIM after" or "STOP after" attributes set, + # automatically delete them. THe new commands will do the same + # thing. + # + # If we didn't delete these here, then things would get confusing. + # If the user were to delete a "trim" symbol added by this extension + # but the "embroider_trim_after" attribute is still set, then the + # trim would keep happening. + + attribute = "embroider_%s_after" % command + + if attribute in element.node.attrib: + del element.node.attrib[attribute] + def add_command(self, element, commands): for i, command in enumerate(commands): + self.remove_legacy_param(element, command) + pos = self.get_command_pos(element, i, len(commands)) symbol = inkex.etree.SubElement(element.node.getparent(), SVG_USE_TAG, @@ -125,4 +143,4 @@ class Commands(InkstitchExtension): self.ensure_symbol(command) for element in self.elements: - self.add_command(element, commands) + self.add_command(element, commands) -- cgit v1.2.3 From 1b63ac5bfa12dc4fc4162a4e7c8e06130e5e906c Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Wed, 4 Jul 2018 23:00:03 -0400 Subject: only process each node once --- lib/extensions/commands.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/extensions/commands.py b/lib/extensions/commands.py index 9c080b4e..4c9fd172 100644 --- a/lib/extensions/commands.py +++ b/lib/extensions/commands.py @@ -142,5 +142,11 @@ class Commands(InkstitchExtension): for command in commands: self.ensure_symbol(command) + # Each object (node) in the SVG may correspond to multiple Elements of different + # types (e.g. stroke + fill). We only want to process each one once. + seen_nodes = set() + for element in self.elements: - self.add_command(element, commands) + if element.node not in seen_nodes: + self.add_command(element, commands) + seen_nodes.add(element.node) -- cgit v1.2.3 From 942afda383ea6444ba9460054e04ad5e0cc5128e Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Thu, 5 Jul 2018 17:26:44 -0400 Subject: change symbol object IDs to avoid conflicts --- symbols/inkstitch.svg | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/symbols/inkstitch.svg b/symbols/inkstitch.svg index a9c3bf17..4497e679 100644 --- a/symbols/inkstitch.svg +++ b/symbols/inkstitch.svg @@ -61,64 +61,64 @@ Fill stitch ending point + id="inkstitch_title9427">Fill stitch ending point Trim the thread after sewing this object. + id="inkstitch_title9282">Trim the thread after sewing this object. Fill stitch starting point + id="inkstitch_title9432">Fill stitch starting point Stop the machine after sewing this object (for applique, etc) + id="inkstitch_title13328">Stop the machine after sewing this object (for applique, etc) -- cgit v1.2.3 From 73565ae691b409af9190a02485e51ed590510384 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Mon, 9 Jul 2018 20:59:46 -0400 Subject: fix stop count --- lib/stitch_plan/stitch_plan.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/stitch_plan/stitch_plan.py b/lib/stitch_plan/stitch_plan.py index 93bcd195..742916f0 100644 --- a/lib/stitch_plan/stitch_plan.py +++ b/lib/stitch_plan/stitch_plan.py @@ -183,10 +183,7 @@ class ColorBlock(object): def num_stops(self): """Number of pauses in this color block.""" - # Stops are encoded using two STOP stitches each. See the comment in - # stop.py for an explanation. - - return sum(1 for stitch in self if stitch.stop) / 2 + return sum(1 for stitch in self if stitch.stop) @property def num_trims(self): -- cgit v1.2.3 From 0c6288f7693a6aeb2d3dd15ad727d868de183b6a Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Tue, 10 Jul 2018 20:03:51 -0400 Subject: perturb the positions of commands a bit --- lib/extensions/commands.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/extensions/commands.py b/lib/extensions/commands.py index 4c9fd172..5767447c 100644 --- a/lib/extensions/commands.py +++ b/lib/extensions/commands.py @@ -4,6 +4,7 @@ import inkex import simpletransform import cubicsuperpath from copy import deepcopy +from random import random from shapely import geometry as shgeo from .base import InkstitchExtension @@ -84,8 +85,16 @@ class Commands(InkstitchExtension): def get_command_pos(self, element, index, total): # Put command symbols 30 pixels out from the shape, spaced evenly around it. + + # get a line running 30 pixels out from the shape outline = element.shape.buffer(30).exterior - return outline.interpolate(index / float(total), normalized=True) + + # pick this item's spot arond the outline and perturb it a bit to avoid + # stacking up commands if they run the extension multiple times + position = index / float(total) + position += random() * 0.1 + + return outline.interpolate(position, normalized=True) def remove_legacy_param(self, element, command): if command == "trim" or command == "stop": -- cgit v1.2.3 From b90d4c152e4c319e74b984207aa369b47af05074 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Tue, 10 Jul 2018 20:07:47 -0400 Subject: make connector 50% transparent --- lib/extensions/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/extensions/commands.py b/lib/extensions/commands.py index 5767447c..2f3006ff 100644 --- a/lib/extensions/commands.py +++ b/lib/extensions/commands.py @@ -73,7 +73,7 @@ class Commands(InkstitchExtension): { "id": self.uniqueId("connector"), "d": "M %s,%s %s,%s" % (start_pos[0], start_pos[1], end_pos.x, end_pos.y), - "style": "stroke:#000000;stroke-width:1px;fill:none;", + "style": "stroke:#000000;stroke-width:1px;stroke-opacity:0.5;fill:none;", "transform": self.get_correction_transform(symbol), CONNECTION_START: "#%s" % symbol.get('id'), CONNECTION_END: "#%s" % element.node.get('id'), -- cgit v1.2.3 From 6caba7b839e9f4e90ab9f3ff1110c8759e30337d Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Tue, 10 Jul 2018 20:12:38 -0400 Subject: fix import --- lib/extensions/__init__.py | 2 +- messages.po | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index dfdc7a3e..8b243176 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -7,4 +7,4 @@ from input import Input from output import Output from zip import Zip from flip import Flip -from commands import * +from commands import Commands diff --git a/messages.po b/messages.po index 621db2e3..34abe079 100644 --- a/messages.po +++ b/messages.po @@ -178,6 +178,12 @@ msgstr "" msgid "Tip: use Path -> Object to Path to convert non-paths." msgstr "" +msgid "Please select one or more objects to which to attach commands." +msgstr "" + +msgid "Please choose one or more commands to attach." +msgstr "" + msgid "" "\n" "\n" -- cgit v1.2.3