summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Neva <github@lexneva.name>2016-10-29 13:28:37 -0400
committerLex Neva <github@lexneva.name>2016-10-29 13:28:37 -0400
commit9249a3ae7730e62cdff282a33e989c1da5d00411 (patch)
tree3411ea81c88ec2928d482cb71fbcf3f29690eeaf
parent579ef18b563544636b8a575cbbc3fbf774931019 (diff)
pep8 fixes
-rw-r--r--PyEmb.py161
-rw-r--r--embroider.py318
-rw-r--r--embroider_params.py6
3 files changed, 255 insertions, 230 deletions
diff --git a/PyEmb.py b/PyEmb.py
index 5ebbf0f3..585cbaf7 100644
--- a/PyEmb.py
+++ b/PyEmb.py
@@ -1,24 +1,25 @@
-#!python
-#!/usr/bin/python
+#!/usr/bin/env python
# http://www.achatina.de/sewing/main/TECHNICL.HTM
import math
import sys
from copy import deepcopy
+
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)
+ return Point(self.x + other.x, self.y + other.y)
def __sub__(self, other):
- return Point(self.x-other.x, self.y-other.y)
+ return Point(self.x - other.x, self.y - other.y)
def mul(self, scalar):
- return Point(self.x*scalar, self.y*scalar)
+ return Point(self.x * scalar, self.y * scalar)
def __mul__(self, other):
if isinstance(other, Point):
@@ -36,13 +37,13 @@ class Point:
raise ValueError("cannot multiply Point by %s" % type(other))
def __repr__(self):
- return "Pt(%s,%s)" % (self.x,self.y)
+ 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))
+ 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())
+ return self.mul(1.0 / self.length())
def rotate_left(self):
return Point(-self.y, self.x)
@@ -54,36 +55,40 @@ class Point:
return Point(int(round(self.x)), int(round(self.y)))
def as_tuple(self):
- return (self.x,self.y)
+ return (self.x, self.y)
def __cmp__(self, other):
return cmp(self.as_tuple(), other.as_tuple())
+
class Stitch(Point):
- def __init__(self, x, y, color=None, jumpStitch=False):
+
+ def __init__(self, x, y, color=None, jump_stitch=False):
Point.__init__(self, x, y)
self.color = color
- self.jumpStitch = jumpStitch
+ self.jump_stitch = jump_stitch
+
class Embroidery:
+
def __init__(self, stitches, pixels_per_millimeter=1):
self.stitches = deepcopy(stitches)
- self.scale(1.0/pixels_per_millimeter)
+ 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):
+ 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)
+ (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
+ 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)
@@ -102,39 +107,39 @@ class Embroidery:
def export_ksm(self):
str = ""
- self.pos = Point(0,0)
+ self.pos = Point(0, 0)
lastColor = None
for stitch in self.stitches:
- if (lastColor!=None and stitch.color!=lastColor):
+ if (lastColor is not None and stitch.color != lastColor):
mode_byte = 0x99
- #dbg.write("Color change!\n")
+ # dbg.write("Color change!\n")
else:
mode_byte = 0x80
- #dbg.write("color still %s\n" % stitch.color)
+ # 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):
+ 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):
+ if (delta.x < 0):
mode_byte |= 0x40
- str+=chr(mode_byte)
+ 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))
+ # 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):
+ if (lastColor is not None and stitch.color != lastColor):
numColors += 1
# color change
self.str += chr(0x80)
@@ -147,26 +152,28 @@ class Embroidery:
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)
+ 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):
+ while (delta.x != 0 or delta.y != 0):
def clamp(v):
- if (v>127):
+ if (v > 127):
v = 127
- if (v<-127):
+ if (v < -127):
v = -127
return v
dx = clamp(delta.x)
dy = clamp(delta.y)
- move(dx,dy)
+ move(dx, dy)
delta.x -= dx
delta.y -= dy
- #dbg.write("Stitch: %s delta %s\n" % (stitch, delta))
+ # dbg.write("Stitch: %s delta %s\n" % (stitch, delta))
self.pos = stitch
return self.str
@@ -187,7 +194,7 @@ class Embroidery:
int(stitch.color[1:3], 16),
int(stitch.color[3:5], 16),
int(stitch.color[5:7], 16))
- if stitch.jumpStitch:
+ if stitch.jump_stitch:
self.str += '"*","JUMP","%f","%f"\n' % (stitch.x, stitch.y)
self.str += '"*","STITCH","%f","%f"\n' % (stitch.x, stitch.y)
lastStitch = stitch
@@ -211,44 +218,48 @@ class Embroidery:
if format == "melco":
fp.write(self.export_melco())
elif format == "csv":
- fp.write(self.export_csv())
+ fp.write(self.export_csv())
elif format == "gcode":
- fp.write(self.export_gcode())
+ fp.write(self.export_gcode())
fp.close()
+
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(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));
+ 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.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.pos = self.pos + self.dir.mul(dist)
self.emb.addStitch(self.pos)
def turn(self, degreesccw):
- radcw = -degreesccw/180.0*3.141592653589
+ 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)
+ 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)
@@ -256,7 +267,9 @@ class Turtle:
def left(self, degreesccw):
self.turn(-degreesccw)
+
class Koch(Turtle):
+
def __init__(self, depth):
Turtle.__init__(self)
@@ -270,18 +283,20 @@ class Koch(Turtle):
fp.close()
def edge(self, depth, dist):
- if (depth==0):
+ if (depth == 0):
self.forward(dist)
else:
- self.edge(depth-1, dist/3.0)
+ self.edge(depth - 1, dist / 3.0)
self.turn(-60.0)
- self.edge(depth-1, dist/3.0)
+ self.edge(depth - 1, dist / 3.0)
self.turn(120.0)
- self.edge(depth-1, dist/3.0)
+ self.edge(depth - 1, dist / 3.0)
self.turn(-60.0)
- self.edge(depth-1, dist/3.0)
+ self.edge(depth - 1, dist / 3.0)
+
class Hilbert(Turtle):
+
def __init__(self, level):
Turtle.__init__(self)
@@ -294,20 +309,20 @@ class Hilbert(Turtle):
# http://en.wikipedia.org/wiki/Hilbert_curve#Python
def hilbert(self, level, angle):
- if (level==0):
+ if (level == 0):
return
self.right(angle)
- self.hilbert(level-1, -angle)
+ self.hilbert(level - 1, -angle)
self.forward(self.size)
self.left(angle)
- self.hilbert(level-1, angle)
+ self.hilbert(level - 1, angle)
self.forward(self.size)
- self.hilbert(level-1, angle)
+ self.hilbert(level - 1, angle)
self.left(angle)
self.forward(self.size)
- self.hilbert(level-1, -angle)
+ self.hilbert(level - 1, -angle)
self.right(angle)
-if (__name__=='__main__'):
- #Koch(4)
+if (__name__ == '__main__'):
+ # Koch(4)
Hilbert(6)
diff --git a/embroider.py b/embroider.py
index 9a527d68..aed5007b 100644
--- a/embroider.py
+++ b/embroider.py
@@ -45,12 +45,14 @@ PyEmb.dbg = dbg
# a 0.5pt stroke becomes a straight line.
STROKE_MIN = 0.5
+
def parse_boolean(s):
if isinstance(s, bool):
return s
else:
return s and (s.lower() in ('yes', 'y', 'true', 't', '1'))
+
def get_param(node, param, default):
value = node.get("embroider_" + param)
@@ -59,11 +61,13 @@ def get_param(node, param, default):
return value.strip()
+
def get_boolean_param(node, param, default=False):
value = get_param(node, param, default)
return parse_boolean(value)
+
def get_float_param(node, param, default=None):
value = get_param(node, param, default)
@@ -72,6 +76,7 @@ def get_float_param(node, param, default=None):
except ValueError:
return default
+
def get_int_param(node, param, default=None):
value = get_param(node, param, default)
@@ -80,6 +85,7 @@ def get_int_param(node, param, default=None):
except ValueError:
return default
+
def parse_path(node):
path = cubicsuperpath.parsePath(node.get("d"))
@@ -96,6 +102,7 @@ def parse_path(node):
return path
+
def flatten(path, flatness):
"""approximate a path containing beziers with a series of points"""
@@ -113,16 +120,17 @@ def flatten(path, flatness):
return flattened
+
def csp_to_shapely_polygon(path):
poly_ary = []
for sub_path in path:
point_ary = []
last_pt = None
for pt in sub_path:
- if (last_pt!=None):
- vp = (pt[0]-last_pt[0],pt[1]-last_pt[1])
- dp = math.sqrt(math.pow(vp[0],2.0)+math.pow(vp[1],2.0))
- #dbg.write("dp %s\n" % dp)
+ if (last_pt is not None):
+ vp = (pt[0] - last_pt[0], pt[1] - last_pt[1])
+ dp = math.sqrt(math.pow(vp[0], 2.0) + math.pow(vp[1], 2.0))
+ # dbg.write("dp %s\n" % dp)
if (dp > 0.01):
# I think too-close points confuse shapely.
point_ary.append(pt)
@@ -137,11 +145,12 @@ def csp_to_shapely_polygon(path):
poly_ary.sort(key=lambda point_list: shgeo.Polygon(point_list).area, reverse=True)
polygon = shgeo.MultiPolygon([(poly_ary[0], poly_ary[1:])])
- #print >> sys.stderr, "polygon valid:", polygon.is_valid
+ # print >> sys.stderr, "polygon valid:", polygon.is_valid
return polygon
class Patch:
+
def __init__(self, color=None, stitches=None):
self.color = color
self.stitches = stitches or []
@@ -152,7 +161,7 @@ class Patch:
else:
raise TypeError("Patch can only be added to another Patch")
- def addStitch(self, stitch):
+ def add_stitch(self, stitch):
self.stitches.append(stitch)
def reverse(self):
@@ -162,53 +171,53 @@ class Patch:
def patches_to_stitches(patch_list, collapse_len_px=0):
stitches = []
- lastStitch = None
- lastColor = None
+ last_stitch = None
+ last_color = None
for patch in patch_list:
- jumpStitch = True
+ jump_stitch = True
for stitch in patch.stitches:
- if lastStitch and lastColor == patch.color:
- l = (stitch - lastStitch).length()
+ if last_stitch and last_color == patch.color:
+ l = (stitch - last_stitch).length()
if l <= 0.1:
# filter out duplicate successive stitches
- jumpStitch = False
+ jump_stitch = False
continue
- if jumpStitch:
+ if jump_stitch:
# consider collapsing jump stitch, if it is pretty short
if l < collapse_len_px:
- #dbg.write("... collapsed\n")
- jumpStitch = False
+ # dbg.write("... collapsed\n")
+ jump_stitch = False
- #dbg.write("stitch color %s\n" % patch.color)
+ # dbg.write("stitch color %s\n" % patch.color)
- newStitch = PyEmb.Stitch(stitch.x, stitch.y, patch.color, jumpStitch)
+ newStitch = PyEmb.Stitch(stitch.x, stitch.y, patch.color, jump_stitch)
stitches.append(newStitch)
- jumpStitch = False
- lastStitch = stitch
- lastColor = patch.color
+ jump_stitch = False
+ last_stitch = stitch
+ last_color = patch.color
return stitches
def stitches_to_paths(stitches):
paths = []
- lastColor = None
- lastStitch = None
+ last_color = None
+ last_stitch = None
for stitch in stitches:
- if stitch.jumpStitch:
- if lastColor == stitch.color:
+ if stitch.jump_stitch:
+ if last_color == stitch.color:
paths.append([None, []])
- if lastStitch is not None:
- paths[-1][1].append(['M', lastStitch.as_tuple()])
+ if last_stitch is not None:
+ paths[-1][1].append(['M', last_stitch.as_tuple()])
paths[-1][1].append(['L', stitch.as_tuple()])
- lastColor = None
- if stitch.color != lastColor:
+ last_color = None
+ if stitch.color != last_color:
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
+ last_color = stitch.color
+ last_stitch = stitch
return paths
@@ -216,69 +225,70 @@ 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),
- })
+ 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):
- #dbg.write("args: %s\n" % repr(sys.argv))
+ # dbg.write("args: %s\n" % repr(sys.argv))
inkex.Effect.__init__(self)
self.OptionParser.add_option("-r", "--row_spacing_mm",
- action="store", type="float",
- dest="row_spacing_mm", default=0.4,
- help="row spacing (mm)")
+ action="store", type="float",
+ dest="row_spacing_mm", default=0.4,
+ help="row spacing (mm)")
self.OptionParser.add_option("-z", "--zigzag_spacing_mm",
- action="store", type="float",
- dest="zigzag_spacing_mm", default=1.0,
- help="zigzag spacing (mm)")
+ action="store", type="float",
+ dest="zigzag_spacing_mm", default=1.0,
+ help="zigzag spacing (mm)")
self.OptionParser.add_option("-l", "--max_stitch_len_mm",
- action="store", type="float",
- dest="max_stitch_len_mm", default=3.0,
- help="max stitch length (mm)")
+ action="store", type="float",
+ dest="max_stitch_len_mm", default=3.0,
+ help="max stitch length (mm)")
self.OptionParser.add_option("--running_stitch_len_mm",
- action="store", type="float",
- dest="running_stitch_len_mm", default=3.0,
- help="running stitch length (mm)")
+ action="store", type="float",
+ dest="running_stitch_len_mm", default=3.0,
+ help="running stitch length (mm)")
self.OptionParser.add_option("-c", "--collapse_len_mm",
- action="store", type="float",
- dest="collapse_len_mm", default=0.0,
- help="max collapse length (mm)")
+ action="store", type="float",
+ dest="collapse_len_mm", default=0.0,
+ help="max collapse length (mm)")
self.OptionParser.add_option("-f", "--flatness",
- action="store", type="float",
- dest="flat", default=0.1,
- help="Minimum flatness of the subdivided curves")
+ action="store", type="float",
+ dest="flat", default=0.1,
+ help="Minimum flatness of the subdivided curves")
self.OptionParser.add_option("--hide_layers",
- action="store", type="choice",
- choices=["true","false"],
- dest="hide_layers", default="true",
- help="Hide all other layers when the embroidery layer is generated")
+ action="store", type="choice",
+ choices=["true", "false"],
+ dest="hide_layers", default="true",
+ help="Hide all other layers when the embroidery layer is generated")
self.OptionParser.add_option("-O", "--output_format",
- action="store", type="choice",
- choices=["melco", "csv", "gcode"],
- dest="output_format", default="melco",
- help="File output format")
+ action="store", type="choice",
+ choices=["melco", "csv", "gcode"],
+ dest="output_format", default="melco",
+ help="File output format")
self.OptionParser.add_option("-P", "--path",
- action="store", type="string",
- dest="path", default=".",
- help="Directory in which to store output file")
+ action="store", type="string",
+ dest="path", default=".",
+ help="Directory in which to store output file")
self.OptionParser.add_option("-b", "--max-backups",
- action="store", type="int",
- dest="max_backups", default=5,
- help="Max number of backups of output files to keep.")
+ action="store", type="int",
+ dest="max_backups", default=5,
+ help="Max number of backups of output files to keep.")
self.OptionParser.add_option("-p", "--pixels_per_mm",
- action="store", type="int",
- dest="pixels_per_millimeter", default=10,
- help="Number of on-screen pixels per millimeter.")
+ action="store", type="int",
+ dest="pixels_per_millimeter", default=10,
+ help="Number of on-screen pixels per millimeter.")
self.patches = []
def process_one_path(self, node, shpath, threadcolor, angle):
- #self.add_shapely_geo_to_svg(shpath.boundary, color="#c0c000")
+ # self.add_shapely_geo_to_svg(shpath.boundary, color="#c0c000")
flip = get_boolean_param(node, "flip", False)
row_spacing_px = get_float_param(node, "row_spacing", self.options.row_spacing_mm) * self.options.pixels_per_millimeter
@@ -287,11 +297,11 @@ class Embroider(inkex.Effect):
rows_of_segments = self.intersect_region_with_grating(shpath, row_spacing_px, angle, flip)
groups_of_segments = self.pull_runs(rows_of_segments, shpath, row_spacing_px)
-
+
# "east" is the name of the direction that is to the right along a row
east = PyEmb.Point(1, 0).rotate(-angle)
- #print >> sys.stderr, len(groups_of_segments)
+ # print >> sys.stderr, len(groups_of_segments)
patches = []
for group_of_segments in groups_of_segments:
@@ -302,7 +312,7 @@ class Embroider(inkex.Effect):
for segment in group_of_segments:
# We want our stitches to look like this:
- #
+ #
# ---*-----------*-----------
# ------*-----------*--------
# ---------*-----------*-----
@@ -324,7 +334,7 @@ class Embroider(inkex.Effect):
(beg, end) = segment
if (swap):
- (beg,end)=(end,beg)
+ (beg, end) = (end, beg)
beg = PyEmb.Point(*beg)
end = PyEmb.Point(*end)
@@ -335,7 +345,7 @@ class Embroider(inkex.Effect):
# only stitch the first point if it's a reasonable distance away from the
# last stitch
if last_end is None or (beg - last_end).length() > 0.5 * self.options.pixels_per_millimeter:
- patch.addStitch(beg)
+ patch.add_stitch(beg)
# Now, imagine the coordinate axes rotated by 'angle' degrees, such that
# the rows are parallel to the X axis. We can find the coordinates in these
@@ -357,11 +367,11 @@ class Embroider(inkex.Effect):
offset = (first_stitch - beg).length()
while offset < segment_length:
- patch.addStitch(beg + offset * row_direction)
+ patch.add_stitch(beg + offset * row_direction)
offset += max_stitch_len_px
if (end - patch.stitches[-1]).length() > 0.1 * self.options.pixels_per_millimeter:
- patch.addStitch(end)
+ patch.add_stitch(end)
last_end = end
swap = not swap
@@ -383,7 +393,7 @@ class Embroider(inkex.Effect):
direction = PyEmb.Point(1, 0).rotate(-angle)
# and get a normal vector
- normal = direction.rotate(math.pi/2)
+ normal = direction.rotate(math.pi / 2)
# I'll start from the center, move in the normal direction some amount,
# and then walk left and right half_length in each direction to create
@@ -395,7 +405,7 @@ class Embroider(inkex.Effect):
# angle degrees clockwise and ask for the new bounding box. The max
# and min y tell me how far to go.
- _, start, _, end = affinity.rotate(shpath, angle, origin='center', use_radians = True).bounds
+ _, start, _, end = affinity.rotate(shpath, angle, origin='center', use_radians=True).bounds
# convert start and end to be relative to center (simplifies things later)
start -= center.y
@@ -450,7 +460,7 @@ class Embroider(inkex.Effect):
# start a new patch.
# Segments more than this far apart are considered not to be part of
- # the same run.
+ # the same run.
row_distance_cutoff = row_spacing_px * 1.1
def make_quadrilateral(segment1, segment2):
@@ -470,10 +480,10 @@ class Embroider(inkex.Effect):
return (intersection_area / quad_area) >= 0.9
- #for row in rows:
+ # for row in rows:
# print >> sys.stderr, len(row)
- #print >>sys.stderr, "\n".join(str(len(row)) for row in rows)
+ # print >>sys.stderr, "\n".join(str(len(row)) for row in rows)
runs = []
count = 0
@@ -488,13 +498,13 @@ class Embroider(inkex.Effect):
# TODO: only accept actually adjacent rows here
if prev is not None and not is_same_run(prev, first):
break
-
+
run.append(first)
prev = first
rows[row_num] = rest
- #print >> sys.stderr, len(run)
+ # print >> sys.stderr, len(run)
runs.append(run)
rows = [row for row in rows if len(row) > 0]
@@ -515,7 +525,7 @@ class Embroider(inkex.Effect):
if node.tag != self.svgpath:
return
- #dbg.write("Node: %s\n"%str((id, etree.tostring(node, pretty_print=True))))
+ # dbg.write("Node: %s\n"%str((id, etree.tostring(node, pretty_print=True))))
if get_boolean_param(node, "satin_column"):
self.patch_list.extend(self.satin_column(node))
@@ -523,9 +533,9 @@ class Embroider(inkex.Effect):
stroke = []
fill = []
- if (self.get_style(node, "stroke")!=None):
+ if (self.get_style(node, "stroke") is not None):
stroke = self.path_to_patch_list(node)
- if (self.get_style(node, "fill")!=None):
+ if (self.get_style(node, "fill") is not None):
fill = self.filled_region_to_patchlist(node)
if get_boolean_param(node, "stroke_first", False):
@@ -540,7 +550,7 @@ class Embroider(inkex.Effect):
if (style_name not in style):
return None
value = style[style_name]
- if (value==None or value=="none"):
+ if (value is None or value == "none"):
return None
return value
@@ -615,7 +625,7 @@ class Embroider(inkex.Effect):
emb.export(self.get_output_path(), self.options.output_format)
new_layer = inkex.etree.SubElement(self.document.getroot(),
- inkex.addNS('g', 'svg'), {})
+ 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')
@@ -624,7 +634,7 @@ class Embroider(inkex.Effect):
sys.stdout = old_stdout
def hide_layers(self):
- for g in self.document.getroot().findall(inkex.addNS("g","svg")):
+ for g in self.document.getroot().findall(inkex.addNS("g", "svg")):
if g.get(inkex.addNS("groupmode", "inkscape")) == "layer":
g.set("style", "display:none")
@@ -637,8 +647,8 @@ class Embroider(inkex.Effect):
stroke_width_str = stroke_width_str[:-2]
stroke_width = float(stroke_width_str)
dashed = self.get_style(node, "stroke-dasharray") is not None
- #dbg.write("stroke_width is <%s>\n" % repr(stroke_width))
- #dbg.flush()
+ # dbg.write("stroke_width is <%s>\n" % repr(stroke_width))
+ # dbg.flush()
running_stitch_len_px = get_float_param(node, "stitch_length", self.options.running_stitch_len_mm) * self.pixels_per_millimeter
zigzag_spacing_px = get_float_param(node, "zigzag_spacing", self.options.zigzag_spacing_mm) * self.options.pixels_per_millimeter
@@ -655,10 +665,10 @@ class Embroider(inkex.Effect):
for path in paths:
path = [PyEmb.Point(x, y) for x, y in path]
if (stroke_width <= STROKE_MIN or dashed):
- #dbg.write("self.max_stitch_len_px = %s\n" % self.max_stitch_len_px)
+ # dbg.write("self.max_stitch_len_px = %s\n" % self.max_stitch_len_px)
patch = self.stroke_points(path, running_stitch_len_px, 0.0, repeats, threadcolor)
else:
- patch = self.stroke_points(path, zigzag_spacing_px*0.5, stroke_width, repeats, threadcolor)
+ patch = self.stroke_points(path, zigzag_spacing_px * 0.5, stroke_width, repeats, threadcolor)
patches.extend(patch)
return patches
@@ -687,19 +697,19 @@ class Embroider(inkex.Effect):
# vector pointing along segment
along = (p1 - p0).unit()
# vector pointing to edge of stroke width
- perp = along.rotate_left().mul(stroke_width*0.5)
+ perp = along.rotate_left().mul(stroke_width * 0.5)
if stroke_width == 0.0 and last_segment_direction is not None:
if abs(1.0 - along * last_segment_direction) > 0.5:
# if greater than 45 degree angle, stitch the corner
- #print >> sys.stderr, "corner", along * last_segment_direction
+ # print >> sys.stderr, "corner", along * last_segment_direction
rho = zigzag_spacing_px
- patch.addStitch(p0)
+ patch.add_stitch(p0)
# iteration variable: how far we are along segment
while (rho <= seg_len):
- left_pt = p0+along.mul(rho)+perp.mul(fact)
- patch.addStitch(left_pt)
+ left_pt = p0 + along.mul(rho) + perp.mul(fact)
+ patch.add_stitch(left_pt)
rho += zigzag_spacing_px
fact = -fact
@@ -708,20 +718,20 @@ class Embroider(inkex.Effect):
rho -= seg_len
if (p0 - patch.stitches[-1]).length() > 0.1:
- patch.addStitch(p0)
+ patch.add_stitch(p0)
return [patch]
def filled_region_to_patchlist(self, node):
- angle = math.radians(float(get_float_param(node,'angle',0)))
+ angle = math.radians(float(get_float_param(node, 'angle', 0)))
paths = flatten(parse_path(node), self.options.flat)
shapelyPolygon = csp_to_shapely_polygon(paths)
threadcolor = simplestyle.parseStyle(node.get("style"))["fill"]
return self.process_one_path(
- node,
- shapelyPolygon,
- threadcolor,
- angle)
+ node,
+ shapelyPolygon,
+ threadcolor,
+ angle)
def fatal(self, message):
print >> sys.stderr, "error:", message
@@ -733,7 +743,7 @@ class Embroider(inkex.Effect):
if len(csp) != 2:
self.fatal("satin column: object %s invalid: expected exactly two sub-paths, but there are %s" % (node_id, len(csp)))
- if self.get_style(node, "fill")!=None:
+ if self.get_style(node, "fill") is not None:
self.fatal("satin column: object %s has a fill (but should not)" % node_id)
if len(csp[0]) != len(csp[1]):
@@ -805,15 +815,15 @@ class Embroider(inkex.Effect):
# if offset is negative, don't contract so far that pos1
# and pos2 switch places
- if offset_px < -distance/2.0:
- offset_px = -distance/2.0
+ if offset_px < -distance / 2.0:
+ offset_px = -distance / 2.0
midpoint = (pos2 + pos1) * 0.5
pos1 = pos1 + (pos1 - midpoint).unit() * offset_px
pos2 = pos2 + (pos2 - midpoint).unit() * offset_px
-
+
return pos1, pos2
-
+
def walk_paths(spacing, offset):
# Take a bezier segment from each path in turn, and plot out an
# equal number of points on each side. Later code can alternate
@@ -821,46 +831,46 @@ class Embroider(inkex.Effect):
side1 = []
side2 = []
-
+
def add_pair(pos1, pos2):
# Stitches in satin tend to pull toward each other. We can compensate
# by spreading the points out.
pos1, pos2 = offset_points(pos1, pos2, offset)
side1.append(pos1)
side2.append(pos2)
-
+
remainder_path1 = []
remainder_path2 = []
-
+
for segment in xrange(1, len(path1)):
# construct the current bezier segments
- bezier1 = (path1[segment - 1][1], # point from previous 3-tuple
- path1[segment - 1][2], # "after" control point from previous 3-tuple
- path1[segment][0], # "before" control point from this 3-tuple
- path1[segment][1], # point from this 3-tuple
- )
-
+ bezier1 = (path1[segment - 1][1], # point from previous 3-tuple
+ path1[segment - 1][2], # "after" control point from previous 3-tuple
+ path1[segment][0], # "before" control point from this 3-tuple
+ path1[segment][1], # point from this 3-tuple
+ )
+
bezier2 = (path2[segment - 1][1],
path2[segment - 1][2],
path2[segment][0],
path2[segment][1],
- )
-
+ )
+
# Here's what I want to be able to do. However, beziertatlength is so incredibly slow that it's unusable.
- #for stitch in xrange(num_zigzags):
- # patch.addStitch(bezierpointatt(bezier1, beziertatlength(bezier1, stitch_len1 * stitch)))
- # patch.addStitch(bezierpointatt(bezier2, beziertatlength(bezier2, stitch_len2 * (stitch + 0.5))))
-
+ # for stitch in xrange(num_zigzags):
+ # patch.add_stitch(bezierpointatt(bezier1, beziertatlength(bezier1, stitch_len1 * stitch)))
+ # patch.add_stitch(bezierpointatt(bezier2, beziertatlength(bezier2, stitch_len2 * (stitch + 0.5))))
+
# Instead, flatten the beziers down to a set of line segments.
subpath1 = remainder_path1 + flatten([[path1[segment - 1], path1[segment]]], self.options.flat)[0]
subpath2 = remainder_path2 + flatten([[path2[segment - 1], path2[segment]]], self.options.flat)[0]
-
+
len1 = shgeo.LineString(subpath1).length
len2 = shgeo.LineString(subpath2).length
-
+
subpath1 = [PyEmb.Point(*p) for p in subpath1]
subpath2 = [PyEmb.Point(*p) for p in subpath2]
-
+
# Base the number of stitches in each section on the _longest_ of
# the two beziers. Otherwise, things could get too sparse when one
# side is significantly longer (e.g. when going around a corner).
@@ -868,73 +878,73 @@ class Embroider(inkex.Effect):
# cram too many stitches on the short bezier. The user will need
# to avoid this through careful construction of paths.
num_points = max(len1, len2) / spacing
-
+
spacing1 = len1 / num_points
spacing2 = len2 / num_points
-
+
def walk(path, start_pos, start_index, distance):
# Move <distance> pixels along <path>'s line segments.
# <start_index> is the index of the line segment in <path> that
# we're currently on. <start_pos> is where along that line
# segment we are. Return a new position and index.
-
+
pos = start_pos
index = start_index
-
+
if index >= len(path) - 1:
# it's possible we'll go too far due to inaccuracy in the
# bezier length calculation
return start_pos, start_index
-
+
while True:
segment_end = path[index + 1]
segment_remaining = (segment_end - pos)
distance_remaining = segment_remaining.length()
-
+
if distance_remaining > distance:
return pos + segment_remaining.unit().mul(distance), index
else:
index += 1
-
+
if index >= len(path) - 1:
return segment_end, index
-
+
distance -= distance_remaining
pos = segment_end
-
+
pos1 = subpath1[0]
i1 = 0
-
+
pos2 = subpath2[0]
i2 = 0
-
+
# if num_zigzags >= 1.0:
# for stitch in xrange(int(num_zigzags) + 1):
for i in xrange(int(num_points)):
add_pair(pos1, pos2)
-
+
pos2, i2 = walk(subpath2, pos2, i2, spacing2)
pos1, i1 = walk(subpath1, pos1, i1, spacing1)
-
+
if i1 < len(subpath1) - 1:
remainder_path1 = [pos1] + subpath1[i1 + 1:]
else:
remainder_path1 = []
-
+
if i2 < len(subpath2) - 1:
remainder_path2 = [pos2] + subpath2[i2 + 1:]
else:
remainder_path2 = []
-
+
remainder_path1 = [p.as_tuple() for p in remainder_path1]
remainder_path2 = [p.as_tuple() for p in remainder_path2]
-
+
# We're off by one in the algorithm above, so we need one more
# pair of points. We also want to add points at the very end to
# make sure we match the vectors on screen as best as possible.
# Try to avoid doing both if they're going to stack up too
# closely.
-
+
end1 = PyEmb.Point(*remainder_path1[-1])
end2 = PyEmb.Point(*remainder_path2[-1])
if (end1 - pos1).length() > 0.3 * spacing:
@@ -963,13 +973,13 @@ class Embroider(inkex.Effect):
patch = Patch(color=threadcolor)
- sides = walk_paths(zigzag_spacing/2.0, -inset)
- sides = [sides[0][::2] + list(reversed(sides[0][1::2])), sides[1][1::2] + list(reversed(sides[1][::2]))]
+ sides = walk_paths(zigzag_spacing / 2.0, -inset)
+ sides = [sides[0][::2] + list(reversed(sides[0][1::2])), sides[1][1::2] + list(reversed(sides[1][::2]))]
# this fancy bit of iterable magic just repeatedly takes a point
# from each list in turn
for point in chain.from_iterable(izip(*sides)):
- patch.addStitch(point)
+ patch.add_stitch(point)
return patch
@@ -984,7 +994,7 @@ class Embroider(inkex.Effect):
sides = walk_paths(zigzag_spacing, pull_compensation)
for point in chain.from_iterable(izip(*sides)):
- patch.addStitch(point)
+ patch.add_stitch(point)
return patch
@@ -1012,7 +1022,7 @@ class Embroider(inkex.Effect):
return [patch]
if __name__ == '__main__':
- sys.setrecursionlimit(100000);
+ sys.setrecursionlimit(100000)
e = Embroider()
e.affect()
dbg.flush()
diff --git a/embroider_params.py b/embroider_params.py
index 20f6c222..ffa14f93 100644
--- a/embroider_params.py
+++ b/embroider_params.py
@@ -14,7 +14,7 @@ import inkex
class EmbroiderParams(inkex.Effect):
def __init__(self, *args, **kwargs):
inkex.Effect.__init__(self)
-
+
self.params = ["zigzag_spacing",
"stitch_length",
"row_spacing",
@@ -31,7 +31,7 @@ class EmbroiderParams(inkex.Effect):
"satin_center_walk",
"satin_zigzag_underlay_spacing",
]
-
+
for param in self.params:
self.OptionParser.add_option("--%s" % param, default="")
@@ -40,7 +40,7 @@ class EmbroiderParams(inkex.Effect):
for param in self.params:
value = getattr(self.options, param).strip()
param = "embroider_" + param
-
+
if node.get(param) is not None and not value:
# only overwrite existing params if they gave a value
continue