summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Neva <lexelby@users.noreply.github.com>2018-02-26 19:42:18 -0500
committerGitHub <noreply@github.com>2018-02-26 19:42:18 -0500
commit4e7520c013d8b7c9f5333c2759bef4878784f42d (patch)
tree97aa3c8bb70ee824466db3550fd086c0983106b8
parente958a7f82c60a07b1b85704f99554ff24d582bce (diff)
user can specify origin for embroidery output by setting up guides (#52)
* user can specify origin using guides * embroidery origin defaults to center of canvas
-rw-r--r--embroider.py2
-rw-r--r--inkstitch.py86
-rw-r--r--messages.po14
3 files changed, 83 insertions, 19 deletions
diff --git a/embroider.py b/embroider.py
index e0c489e4..265cbe0f 100644
--- a/embroider.py
+++ b/embroider.py
@@ -1763,7 +1763,7 @@ class Embroider(inkex.Effect):
patches = elements_to_patches(self.elements)
stitches = patches_to_stitches(patches, self.options.collapse_length_mm * PIXELS_PER_MM)
- inkstitch.write_embroidery_file(self.get_output_path(), stitches)
+ inkstitch.write_embroidery_file(self.get_output_path(), stitches, self.document.getroot())
new_layer = inkex.etree.SubElement(self.document.getroot(), SVG_GROUP_TAG, {})
new_layer.set('id', self.uniqueId("embroidery"))
diff --git a/inkstitch.py b/inkstitch.py
index 8a87b160..ba120be0 100644
--- a/inkstitch.py
+++ b/inkstitch.py
@@ -14,6 +14,7 @@ import simpletransform
from bezmisc import bezierlength, beziertatlength, bezierpointatt
from cspsubdiv import cspsubdiv
import cubicsuperpath
+from shapely import geometry as shgeo
try:
@@ -127,11 +128,16 @@ def convert_length(length):
@cache
+def get_doc_size(svg):
+ doc_width = convert_length(svg.get('width'))
+ doc_height = convert_length(svg.get('height'))
+
+ return doc_width, doc_height
+
+@cache
def get_viewbox_transform(node):
# somewhat cribbed from inkscape-silhouette
-
- doc_width = convert_length(node.get('width'))
- doc_height = convert_length(node.get('height'))
+ doc_width, doc_height = get_doc_size(node)
viewbox = node.get('viewBox').strip().replace(',', ' ').split()
@@ -504,12 +510,70 @@ def get_flags(stitch):
return flags
-def write_embroidery_file(file_path, stitches):
- # Embroidery machines don't care about our canvas size, so we relocate the
- # design to the origin. It might make sense to center it about the origin
- # instead.
- min_x = min(stitch.x for stitch in stitches)
- min_y = min(stitch.y for stitch in stitches)
+
+def _string_to_floats(string):
+ floats = string.split(',')
+ return [float(num) for num in floats]
+
+
+def get_origin(svg):
+ # The user can specify the embroidery origin by defining two guides
+ # named "embroidery origin" that intersect.
+
+ namedview = svg.find(inkex.addNS('namedview', 'sodipodi'))
+ all_guides = namedview.findall(inkex.addNS('guide', 'sodipodi'))
+ label_attribute = inkex.addNS('label', 'inkscape')
+ guides = [guide for guide in all_guides
+ if guide.get(label_attribute, "").startswith("embroidery origin")]
+
+ # document size used below
+ doc_size = list(get_doc_size(svg))
+
+ # convert the size from viewbox-relative to real-world pixels
+ viewbox_transform = get_viewbox_transform(svg)
+ simpletransform.applyTransformToPoint(simpletransform.invertTransform(viewbox_transform), doc_size)
+
+ default = [doc_size[0] / 2.0, doc_size[1] / 2.0]
+ simpletransform.applyTransformToPoint(viewbox_transform, default)
+ default = Point(*default)
+
+ if len(guides) < 2:
+ return default
+
+ # Find out where the guides intersect. Only pay attention to the first two.
+ guides = guides[:2]
+
+ lines = []
+ for guide in guides:
+ # inkscape's Y axis is reversed from SVG's, and the guide is in inkscape coordinates
+ position = Point(*_string_to_floats(guide.get('position')))
+ position.y = doc_size[1] - position.y
+
+
+ # This one baffles me. I think inkscape might have gotten the order of
+ # their vector wrong?
+ parts = _string_to_floats(guide.get('orientation'))
+ direction = Point(parts[1], parts[0])
+
+ # We have a theoretically infinite line defined by a point on the line
+ # and a vector direction. Shapely can only deal in concrete line
+ # segments, so we'll pick points really far in either direction on the
+ # line and call it good enough.
+ lines.append(shgeo.LineString((position + 100000 * direction, position - 100000 * direction)))
+
+ intersection = lines[0].intersection(lines[1])
+
+ if isinstance(intersection, shgeo.Point):
+ origin = [intersection.x, intersection.y]
+ simpletransform.applyTransformToPoint(viewbox_transform, origin)
+ return Point(*origin)
+ else:
+ # Either the two guides are the same line, or they're parallel.
+ return default
+
+
+def write_embroidery_file(file_path, stitches, svg):
+ origin = get_origin(svg)
pattern = libembroidery.embPattern_create()
last_color = None
@@ -520,9 +584,9 @@ def write_embroidery_file(file_path, stitches):
last_color = stitch.color
flags = get_flags(stitch)
- libembroidery.embPattern_addStitchAbs(pattern, stitch.x - min_x, stitch.y - min_y, flags, 1)
+ libembroidery.embPattern_addStitchAbs(pattern, stitch.x - origin.x, stitch.y - origin.y, flags, 1)
- libembroidery.embPattern_addStitchAbs(pattern, stitch.x - min_x, stitch.y - min_y, libembroidery.END, 1)
+ libembroidery.embPattern_addStitchAbs(pattern, stitch.x - origin.x, stitch.y - origin.y, libembroidery.END, 1)
# convert from pixels to millimeters
libembroidery.embPattern_scale(pattern, 1/PIXELS_PER_MM)
diff --git a/messages.po b/messages.po
index aca21c60..0f635343 100644
--- a/messages.po
+++ b/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-02-24 20:25-0500\n"
+"POT-Creation-Date: 2018-02-26 19:33-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -312,29 +312,29 @@ msgstr ""
msgid "Embroidery Simulation"
msgstr ""
-#: inkstitch.py:94
+#: inkstitch.py:95
#, python-format
msgid "parseLengthWithUnits: unknown unit %s"
msgstr ""
-#: inkstitch.py:126
+#: inkstitch.py:127
#, python-format
msgid "Unknown unit: %s"
msgstr ""
-#: inkstitch.py:329
+#: inkstitch.py:335
msgid "TRIM after"
msgstr ""
-#: inkstitch.py:330
+#: inkstitch.py:336
msgid "Trim thread after this object (for supported machines and file formats)"
msgstr ""
-#: inkstitch.py:339
+#: inkstitch.py:345
msgid "STOP after"
msgstr ""
-#: inkstitch.py:340
+#: inkstitch.py:346
msgid ""
"Add STOP instruction after this object (for supported machines and file "
"formats)"