inkstitch/PyEmb.py

314 wiersze
9.4 KiB
Python
Czysty Zwykły widok Historia

#!python
#!/usr/bin/python
# http://www.achatina.de/sewing/main/TECHNICL.HTM
import math
import sys
from copy import deepcopy
class Point:
2016-10-27 16:48:12 +00:00
def __init__(self, x, y):
self.x = x
self.y = y
2016-10-27 16:48:12 +00:00
def __add__(self, other):
return Point(self.x+other.x, self.y+other.y)
2016-10-27 16:48:12 +00:00
def __sub__(self, other):
return Point(self.x-other.x, self.y-other.y)
2016-10-27 16:48:12 +00:00
def mul(self, scalar):
return Point(self.x*scalar, self.y*scalar)
2016-10-27 16:49:05 +00:00
2016-10-27 16:48:12 +00:00
def __mul__(self, other):
if isinstance(other, Point):
# dot product
return self.x * other.x + self.y * other.y
elif isinstance(other, (int, float)):
return self.mul(other)
else:
raise ValueError("cannot multiply Point by %s" % type(other))
2016-02-14 03:13:47 +00:00
2016-10-27 16:48:12 +00:00
def __rmul__(self, other):
if isinstance(other, (int, float)):
return self.mul(other)
else:
raise ValueError("cannot multiply Point by %s" % type(other))
2016-02-14 03:13:47 +00:00
2016-10-27 16:48:12 +00:00
def __repr__(self):
return "Pt(%s,%s)" % (self.x,self.y)
2016-10-27 16:48:12 +00:00
def length(self):
return math.sqrt(math.pow(self.x,2.0)+math.pow(self.y,2.0))
2016-10-27 16:48:12 +00:00
def unit(self):
return self.mul(1.0/self.length())
2016-10-27 16:48:12 +00:00
def rotate_left(self):
return Point(-self.y, self.x)
2016-10-27 16:48:12 +00:00
def rotate(self, angle):
return Point(self.x * math.cos(angle) - self.y * math.sin(angle), self.y * math.cos(angle) + self.x * math.sin(angle))
2015-12-15 06:09:25 +00:00
2016-10-27 16:48:12 +00:00
def as_int(self):
return Point(int(round(self.x)), int(round(self.y)))
2016-10-27 16:48:12 +00:00
def as_tuple(self):
return (self.x,self.y)
2016-10-27 16:48:12 +00:00
def __cmp__(self, other):
return cmp(self.as_tuple(), other.as_tuple())
class Stitch(Point):
def __init__(self, x, y, color=None, jumpStitch=False):
Point.__init__(self, x, y)
self.color = color
self.jumpStitch = jumpStitch
class Embroidery:
2016-10-27 16:48:12 +00:00
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.stitches)==0):
return
(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)
maxy = max(maxy,p.y)
sx = maxx-minx
sy = maxy-miny
self.translate(-minx, -miny)
return (minx, miny)
def translate(self, dx, dy):
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.stitches:
p.x *= sc[0]
p.y *= sc[1]
2016-10-27 16:49:05 +00:00
2016-10-27 16:48:12 +00:00
def export_ksm(self):
str = ""
self.pos = Point(0,0)
lastColor = None
for stitch in self.stitches:
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):
self.str = ""
self.pos = self.stitches[0]
#dbg.write("stitch count: %d\n" % len(self.stitches))
lastColor = None
numColors = 0x0
for stitch in self.stitches[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)
2016-10-27 16:49:05 +00:00
2016-10-27 16:48:12 +00:00
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
2016-10-27 16:49:05 +00:00
2016-10-27 16:48:12 +00:00
#dbg.write("Stitch: %s delta %s\n" % (stitch, delta))
self.pos = stitch
return self.str
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.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:
colorIndex += 1
self.str += '"$","%d","%d","%d","%d","(null)","(null)"\n' % (
colorIndex,
int(stitch.color[1:3], 16),
int(stitch.color[3:5], 16),
int(stitch.color[5:7], 16))
if stitch.jumpStitch:
self.str += '"*","JUMP","%f","%f"\n' % (stitch.x, stitch.y)
self.str += '"*","STITCH","%f","%f"\n' % (stitch.x, stitch.y)
lastStitch = stitch
self.str += '"*","END","%f","%f"\n' % (lastStitch.x, lastStitch.y)
return self.str
def export_gcode(self):
ret = []
lastColor = None
for stitch in self.stitches:
if stitch.color != lastColor:
ret.append('M0 ;MSG, Color change; prepare for %s\n' % stitch.color)
lastColor = stitch.color
ret.append('G1 X%f Y%f\n' % stitch.as_tuple())
ret.append('M0 ;MSG, EMBROIDER stitch\n')
return ''.join(ret)
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()
2014-12-27 16:30:54 +00:00
class Test:
2016-10-27 16:48:12 +00:00
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:
2016-10-27 16:48:12 +00:00
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)
2016-10-27 16:49:05 +00:00
class Koch(Turtle):
2016-10-27 16:48:12 +00:00
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()
2016-10-27 16:49:05 +00:00
2016-10-27 16:48:12 +00:00
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):
2016-10-27 16:48:12 +00:00
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__'):
2016-10-27 16:48:12 +00:00
#Koch(4)
Hilbert(6)