diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2018-02-26 19:42:18 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-26 19:42:18 -0500 |
| commit | 4e7520c013d8b7c9f5333c2759bef4878784f42d (patch) | |
| tree | 97aa3c8bb70ee824466db3550fd086c0983106b8 /inkstitch.py | |
| parent | e958a7f82c60a07b1b85704f99554ff24d582bce (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
Diffstat (limited to 'inkstitch.py')
| -rw-r--r-- | inkstitch.py | 86 |
1 files changed, 75 insertions, 11 deletions
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) |
