kopia lustrzana https://github.com/inkstitch/inkstitch
user can specify origin for embroidery output by setting up guides (#52)
* user can specify origin using guides * embroidery origin defaults to center of canvaspull/101/head^2
rodzic
e958a7f82c
commit
4e7520c013
|
|
@ -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"))
|
||||
|
|
|
|||
86
inkstitch.py
86
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:
|
||||
|
|
@ -126,12 +127,17 @@ def convert_length(length):
|
|||
raise ValueError(_("Unknown unit: %s") % units)
|
||||
|
||||
|
||||
@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)
|
||||
|
|
|
|||
14
messages.po
14
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)"
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue