summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PyEmb.py78
-rw-r--r--embroider.py162
2 files changed, 105 insertions, 135 deletions
diff --git a/PyEmb.py b/PyEmb.py
index 44fcc7e4..18fd07fb 100644
--- a/PyEmb.py
+++ b/PyEmb.py
@@ -4,6 +4,7 @@
import math
import sys
+from copy import deepcopy
class Point:
def __init__(self, x, y):
@@ -58,20 +59,25 @@ class Point:
def __cmp__(self, other):
return cmp(self.as_tuple(), other.as_tuple())
-class Embroidery:
- def __init__(self):
- self.coords = []
+class Stitch(Point):
+ def __init__(self, x, y, color=None, jumpStitch=False):
+ Point.__init__(self, x, y)
+ self.color = color
+ self.jumpStitch = jumpStitch
- def addStitch(self, coord):
- if len(self.coords) == 0 or self.coords[-1] != coord:
- self.coords.append(coord)
+class Embroidery:
+ def __init__(self, stitches, pixels_per_millimeter=1):
+ self.stitches = deepcopy(stitches)
+ self.scale(1.0/pixels_per_millimeter)
+ self.scale((1, -1))
+ self.translate_to_origin()
def translate_to_origin(self):
- if (len(self.coords)==0):
+ if (len(self.stitches)==0):
return
- (maxx,maxy) = (self.coords[0].x,self.coords[0].y)
- (minx,miny) = (self.coords[0].x,self.coords[0].y)
- for p in self.coords:
+ (maxx,maxy) = (self.stitches[0].x,self.stitches[0].y)
+ (minx,miny) = (self.stitches[0].x,self.stitches[0].y)
+ for p in self.stitches:
minx = min(minx,p.x)
miny = min(miny,p.y)
maxx = max(maxx,p.x)
@@ -83,22 +89,22 @@ class Embroidery:
return (minx, miny)
def translate(self, dx, dy):
- for p in self.coords:
+ for p in self.stitches:
p.x += dx
p.y += dy
def scale(self, sc):
if not isinstance(sc, (tuple, list)):
sc = (sc, sc)
- for p in self.coords:
+ for p in self.stitches:
p.x *= sc[0]
p.y *= sc[1]
- def export_ksm(self, dbg):
+ def export_ksm(self):
str = ""
self.pos = Point(0,0)
lastColor = None
- for stitch in self.coords:
+ for stitch in self.stitches:
if (lastColor!=None and stitch.color!=lastColor):
mode_byte = 0x99
#dbg.write("Color change!\n")
@@ -121,13 +127,13 @@ class Embroidery:
self.pos = stitch
return str
- def export_melco(self, dbg):
+ def export_melco(self):
self.str = ""
- self.pos = self.coords[0]
- #dbg.write("stitch count: %d\n" % len(self.coords))
+ self.pos = self.stitches[0]
+ #dbg.write("stitch count: %d\n" % len(self.stitches))
lastColor = None
numColors = 0x0
- for stitch in self.coords[1:]:
+ for stitch in self.stitches[1:]:
if (lastColor!=None and stitch.color!=lastColor):
numColors += 1
# color change
@@ -164,14 +170,14 @@ class Embroidery:
self.pos = stitch
return self.str
- def export_csv(self, dbg):
+ def export_csv(self):
self.str = ""
self.str += '"#","[THREAD_NUMBER]","[RED]","[GREEN]","[BLUE]","[DESCRIPTION]","[CATALOG_NUMBER]"\n'
self.str += '"#","[STITCH_TYPE]","[X]","[Y]"\n'
lastStitch = None
colorIndex = 0
- for stitch in self.coords:
+ for stitch in self.stitches:
if lastStitch is not None and stitch.color != lastStitch.color:
self.str += '"*","COLOR","%f","%f"\n' % (lastStitch.x, lastStitch.y)
if lastStitch is None or stitch.color != lastStitch.color:
@@ -188,10 +194,10 @@ class Embroidery:
self.str += '"*","END","%f","%f"\n' % (lastStitch.x, lastStitch.y)
return self.str
- def export_gcode(self, dbg):
+ def export_gcode(self):
ret = []
lastColor = None
- for stitch in self.coords:
+ for stitch in self.stitches:
if stitch.color != lastColor:
ret.append('M0 ;MSG, Color change; prepare for %s\n' % stitch.color)
lastColor = stitch.color
@@ -199,24 +205,16 @@ class Embroidery:
ret.append('M0 ;MSG, EMBROIDER stitch\n')
return ''.join(ret)
- def export_paths(self, dbg):
- paths = []
- lastColor = None
- lastStitch = None
- for stitch in self.coords:
- if stitch.jumpStitch:
- if lastColor == stitch.color:
- paths.append([None, []])
- if lastStitch is not None:
- paths[-1][1].append(['M', lastStitch.as_tuple()])
- paths[-1][1].append(['L', stitch.as_tuple()])
- lastColor = None
- if stitch.color != lastColor:
- paths.append([stitch.color, []])
- paths[-1][1].append(['L' if len(paths[-1][1]) > 0 else 'M', stitch.as_tuple()])
- lastColor = stitch.color
- lastStitch = stitch
- return paths
+ def export(self, filename, format):
+ fp = open(filename, "wb")
+
+ if format == "melco":
+ fp.write(self.export_melco())
+ elif format == "csv":
+ fp.write(self.export_csv())
+ elif format == "gcode":
+ fp.write(self.export_gcode())
+ fp.close()
class Test:
def __init__(self):
diff --git a/embroider.py b/embroider.py
index a472c837..857d2be0 100644
--- a/embroider.py
+++ b/embroider.py
@@ -46,7 +46,7 @@ dbg = open("/tmp/embroider-debug.txt", "w")
PyEmb.dbg = dbg
#pixels_per_millimeter = 90.0 / 25.4
-#this actually makes each pixel worth one tenth of a millimeter
+#this makes each pixel worth one tenth of a millimeter
pixels_per_millimeter = 10
# a 0.5pt stroke becomes a straight line.
@@ -189,80 +189,69 @@ class Patch:
def reverse(self):
return Patch(self.color, self.stitches[::-1])
-class EmbroideryObject:
- def __init__(self, patch_list):
- self.patch_list = patch_list
-
- def emit_file(self, filename, output_format, collapse_len_px):
- emb = PyEmb.Embroidery()
- lastStitch = None
- lastColor = None
- for patch in self.patch_list:
- jumpStitch = True
- for stitch in patch.stitches:
- if lastStitch and lastColor == patch.color:
- c = math.sqrt((stitch.x - lastStitch.x) ** 2 + (stitch.y - lastStitch.y) ** 2)
- #dbg.write("stitch length: %f (%d/%d -> %d/%d)\n" % (c, lastStitch.x, lastStitch.y, stitch.x, stitch.y))
-
- if c <= 0.1:
- # filter out duplicate successive stitches
+def patches_to_stitches(patch_list, collapse_len_px=0):
+ stitches = []
+
+ lastStitch = None
+ lastColor = None
+ for patch in patch_list:
+ jumpStitch = True
+ for stitch in patch.stitches:
+ if lastStitch and lastColor == patch.color:
+ l = (stitch - lastStitch).length()
+ if l <= 0.1:
+ # filter out duplicate successive stitches
+ jumpStitch = False
+ continue
+
+ if jumpStitch:
+ # consider collapsing jump stitch, if it is pretty short
+ if l < collapse_len_px:
+ #dbg.write("... collapsed\n")
jumpStitch = False
- continue
-
- if jumpStitch:
- # consider collapsing jump stich, if it is pretty short
- if c < collapse_len_px:
- #dbg.write("... collapsed\n")
- jumpStitch = False
-
- #dbg.write("stitch color %s\n" % patch.color)
-
- newStitch = PyEmb.Point(stitch.x, -stitch.y)
- newStitch.color = patch.color
- newStitch.jumpStitch = jumpStitch
- emb.addStitch(newStitch)
-
- jumpStitch = False
- lastStitch = newStitch
- lastColor = patch.color
-
- dx, dy = emb.translate_to_origin()
- emb.scale(1.0/pixels_per_millimeter)
-
- fp = open(filename, "wb")
-
- if output_format == "melco":
- fp.write(emb.export_melco(dbg))
- elif output_format == "csv":
- fp.write(emb.export_csv(dbg))
- elif output_format == "gcode":
- fp.write(emb.export_gcode(dbg))
- fp.close()
- emb.scale(pixels_per_millimeter)
- emb.translate(dx, dy)
- return emb
-
- def emit_inkscape(self, parent, emb):
- emb.scale((1, -1));
- for color, path in emb.export_paths(dbg):
- dbg.write('path: %s %s\n' % (color, repr(path)))
- inkex.etree.SubElement(parent,
- inkex.addNS('path', 'svg'),
- { 'style':simplestyle.formatStyle(
- { 'stroke': color if color is not None else '#000000',
- 'stroke-width':"0.4",
- 'fill': 'none' }),
- 'd':simplepath.formatPath(path),
- })
-
- def bbox(self):
- x = []
- y = []
- for patch in self.patch_list:
- for stitch in patch.stitches:
- x.append(stitch.x)
- y.append(stitch.y)
- return (min(x), min(y), max(x), max(y))
+
+ #dbg.write("stitch color %s\n" % patch.color)
+
+ newStitch = PyEmb.Stitch(stitch.x, stitch.y, patch.color, jumpStitch)
+ stitches.append(newStitch)
+
+ jumpStitch = False
+ lastStitch = stitch
+ lastColor = patch.color
+
+ return stitches
+
+def stitches_to_paths(stitches):
+ paths = []
+ lastColor = None
+ lastStitch = None
+ for stitch in stitches:
+ if stitch.jumpStitch:
+ if lastColor == stitch.color:
+ paths.append([None, []])
+ if lastStitch is not None:
+ paths[-1][1].append(['M', lastStitch.as_tuple()])
+ paths[-1][1].append(['L', stitch.as_tuple()])
+ lastColor = None
+ if stitch.color != lastColor:
+ paths.append([stitch.color, []])
+ paths[-1][1].append(['L' if len(paths[-1][1]) > 0 else 'M', stitch.as_tuple()])
+ lastColor = stitch.color
+ lastStitch = stitch
+ return paths
+
+
+def emit_inkscape(parent, stitches):
+ for color, path in stitches_to_paths(stitches):
+ dbg.write('path: %s %s\n' % (color, repr(path)))
+ inkex.etree.SubElement(parent,
+ inkex.addNS('path', 'svg'),
+ { 'style':simplestyle.formatStyle(
+ { 'stroke': color if color is not None else '#000000',
+ 'stroke-width':"0.4",
+ 'fill': 'none' }),
+ 'd':simplepath.formatPath(path),
+ })
class Embroider(inkex.Effect):
def __init__(self, *args, **kwargs):
@@ -662,36 +651,19 @@ class Embroider(inkex.Effect):
if self.options.hide_layers:
self.hide_layers()
- eo = EmbroideryObject(self.patch_list)
- emb = eo.emit_file(self.get_output_path(), self.options.output_format,
- self.collapse_len_px)
+ stitches = patches_to_stitches(self.patch_list, self.collapse_len_px)
+ emb = PyEmb.Embroidery(stitches, pixels_per_millimeter)
+ emb.export(self.get_output_path(), self.options.output_format)
new_layer = inkex.etree.SubElement(self.document.getroot(),
inkex.addNS('g', 'svg'), {})
new_layer.set('id', self.uniqueId("embroidery"))
new_layer.set(inkex.addNS('label', 'inkscape'), 'Embroidery')
new_layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
- eo.emit_inkscape(new_layer, emb)
+ emit_inkscape(new_layer, stitches)
sys.stdout = old_stdout
- def emit_inkscape_bbox(self, parent, eo):
- (x0, y0, x1, y1) = eo.bbox()
- new_path = []
- new_path.append(['M', (x0,y0)])
- new_path.append(['L', (x1,y0)])
- new_path.append(['L', (x1,y1)])
- new_path.append(['L', (x0,y1)])
- new_path.append(['L', (x0,y0)])
- inkex.etree.SubElement(parent,
- inkex.addNS('path', 'svg'),
- { 'style':simplestyle.formatStyle(
- { 'stroke': '#ff00ff',
- 'stroke-width':str(1),
- 'fill': 'none' }),
- 'd':simplepath.formatPath(new_path),
- })
-
def hide_layers(self):
for g in self.document.getroot().findall(inkex.addNS("g","svg")):
if g.get(inkex.addNS("groupmode", "inkscape")) == "layer":