summaryrefslogtreecommitdiff
path: root/PyEmb.py
diff options
context:
space:
mode:
authorStefan Siegl <stesie@brokenpipe.de>2014-12-26 23:15:48 +0100
committerStefan Siegl <stesie@brokenpipe.de>2014-12-26 23:15:48 +0100
commit47449d22cb9ef299d6cd9d8661e4d1f5fcb09f2a (patch)
tree83fd36e50eb8af74e9572dc943f8a6aaa1c562cc /PyEmb.py
Initial import of upstream code
Embroidery output extension for Inkscape; downloaded from http://www.jonh.net/~jonh/inkscape-embroidery/ on 2014-12-26 19:38 CET Copyright 2010 by Jon Howell, licensed under GPLv3.
Diffstat (limited to 'PyEmb.py')
-rw-r--r--PyEmb.py241
1 files changed, 241 insertions, 0 deletions
diff --git a/PyEmb.py b/PyEmb.py
new file mode 100644
index 00000000..6f14fded
--- /dev/null
+++ b/PyEmb.py
@@ -0,0 +1,241 @@
+#!python
+#!/usr/bin/python
+# http://www.achatina.de/sewing/main/TECHNICL.HTM
+
+import math
+import sys
+dbg = sys.stderr
+
+def abs(x):
+ if (x<0): return -x
+ return x
+
+class Point:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def __add__(self, other):
+ return Point(self.x+other.x, self.y+other.y)
+
+ def __sub__(self, other):
+ return Point(self.x-other.x, self.y-other.y)
+
+ def mul(self, scalar):
+ return Point(self.x*scalar, self.y*scalar)
+
+ def __repr__(self):
+ return "Pt(%s,%s)" % (self.x,self.y)
+
+ def length(self):
+ return math.sqrt(math.pow(self.x,2.0)+math.pow(self.y,2.0))
+
+ def unit(self):
+ return self.mul(1.0/self.length())
+
+ def rotate_left(self):
+ return Point(-self.y, self.x)
+
+ def as_int(self):
+ return Point(int(round(self.x)), int(round(self.y)))
+
+ def as_tuple(self):
+ return (self.x,self.y)
+
+ def __cmp__(self, other):
+ return cmp(self.as_tuple(), other.as_tuple())
+
+class Embroidery:
+ def __init__(self):
+ self.coords = []
+
+ def addStitch(self, coord):
+ self.coords.append(coord)
+
+ def translate_to_origin(self):
+ if (len(self.coords)==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:
+ minx = min(minx,p.x)
+ miny = min(miny,p.y)
+ maxx = max(maxx,p.x)
+ maxy = max(maxy,p.y)
+ sx = maxx-minx
+ sy = maxy-miny
+ for p in self.coords:
+ p.x -= minx
+ p.y -= miny
+ dbg.write("Field size %s x %s\n" % (sx,sy))
+
+ def scale(self, sc):
+ for p in self.coords:
+ p.x *= sc
+ p.y *= sc
+
+ def export_ksm(self, dbg):
+ str = ""
+ self.pos = Point(0,0)
+ lastColor = None
+ for stitch in self.coords:
+ if (lastColor!=None and stitch.color!=lastColor):
+ mode_byte = 0x99
+ #dbg.write("Color change!\n")
+ else:
+ mode_byte = 0x80
+ #dbg.write("color still %s\n" % stitch.color)
+ lastColor = stitch.color
+ new_int = stitch.as_int()
+ old_int = self.pos.as_int()
+ delta = new_int - old_int
+ assert(abs(delta.x)<=127)
+ assert(abs(delta.y)<=127)
+ str+=chr(abs(delta.y))
+ str+=chr(abs(delta.x))
+ if (delta.y<0):
+ mode_byte |= 0x20
+ if (delta.x<0):
+ mode_byte |= 0x40
+ str+=chr(mode_byte)
+ self.pos = stitch
+ return str
+
+ def export_melco(self, dbg):
+ self.str = ""
+ self.pos = self.coords[0]
+ dbg.write("stitch count: %d\n" % len(self.coords))
+ lastColor = None
+ numColors = 0x0
+ for stitch in self.coords[1:]:
+ if (lastColor!=None and stitch.color!=lastColor):
+ numColors += 1
+ # color change
+ self.str += chr(0x80)
+ self.str += chr(0x01)
+# self.str += chr(numColors)
+# self.str += chr(((numColors+0x80)>>8)&0xff)
+# self.str += chr(((numColors+0x80)>>0)&0xff)
+ lastColor = stitch.color
+ new_int = stitch.as_int()
+ old_int = self.pos.as_int()
+ delta = new_int - old_int
+
+ def move(x,y):
+ if (x<0): x = x + 256
+ self.str+=chr(x)
+ if (y<0): y = y + 256
+ self.str+=chr(y)
+
+ while (delta.x!=0 or delta.y!=0):
+ def clamp(v):
+ if (v>127):
+ v = 127
+ if (v<-127):
+ v = -127
+ return v
+ dx = clamp(delta.x)
+ dy = clamp(delta.y)
+ move(dx,dy)
+ delta.x -= dx
+ delta.y -= dy
+
+ #dbg.write("Stitch: %s delta %s\n" % (stitch, delta))
+ self.pos = stitch
+ return self.str
+
+class Test:
+ def __init__(self):
+ emb = Embroidery()
+ for x in range(0,301,30):
+ emb.addStitch(Point(x, 0));
+ emb.addStitch(Point(x, 15));
+ emb.addStitch(Point(x, 0));
+
+ for x in range(300,-1,-30):
+ emb.addStitch(Point(x, -12));
+ emb.addStitch(Point(x, -27));
+ emb.addStitch(Point(x, -12));
+
+ fp = open("test.exp", "wb")
+ fp.write(emb.export_melco())
+ fp.close()
+
+class Turtle:
+ def __init__(self):
+ self.emb = Embroidery()
+ self.pos = Point(0.0,0.0)
+ self.dir = Point(1.0,0.0)
+ self.emb.addStitch(self.pos)
+
+ def forward(self, dist):
+ self.pos = self.pos+self.dir.mul(dist)
+ self.emb.addStitch(self.pos)
+
+ def turn(self, degreesccw):
+ radcw = -degreesccw/180.0*3.141592653589
+ self.dir = Point(
+ math.cos(radcw)*self.dir.x-math.sin(radcw)*self.dir.y,
+ math.sin(radcw)*self.dir.x+math.cos(radcw)*self.dir.y)
+
+ def right(self, degreesccw):
+ self.turn(degreesccw)
+
+ def left(self, degreesccw):
+ self.turn(-degreesccw)
+
+class Koch(Turtle):
+ def __init__(self, depth):
+ Turtle.__init__(self)
+
+ edgelen = 750.0
+ for i in range(3):
+ self.edge(depth, edgelen)
+ self.turn(120.0)
+
+ fp = open("koch%d.exp" % depth, "wb")
+ fp.write(self.emb.export_melco())
+ fp.close()
+
+ def edge(self, depth, dist):
+ if (depth==0):
+ self.forward(dist)
+ else:
+ self.edge(depth-1, dist/3.0)
+ self.turn(-60.0)
+ self.edge(depth-1, dist/3.0)
+ self.turn(120.0)
+ self.edge(depth-1, dist/3.0)
+ self.turn(-60.0)
+ self.edge(depth-1, dist/3.0)
+
+class Hilbert(Turtle):
+ def __init__(self, level):
+ Turtle.__init__(self)
+
+ self.size = 10.0
+ self.hilbert(level, 90.0)
+
+ fp = open("hilbert%d.exp" % level, "wb")
+ fp.write(self.emb.export_melco())
+ fp.close()
+
+ # http://en.wikipedia.org/wiki/Hilbert_curve#Python
+ def hilbert(self, level, angle):
+ if (level==0):
+ return
+ self.right(angle)
+ self.hilbert(level-1, -angle)
+ self.forward(self.size)
+ self.left(angle)
+ self.hilbert(level-1, angle)
+ self.forward(self.size)
+ self.hilbert(level-1, angle)
+ self.left(angle)
+ self.forward(self.size)
+ self.hilbert(level-1, -angle)
+ self.right(angle)
+
+if (__name__=='__main__'):
+ #Koch(4)
+ Hilbert(6)