summaryrefslogtreecommitdiff
path: root/embroider.py
diff options
context:
space:
mode:
authorLex Neva <github@lexneva.name>2017-09-24 01:56:53 +0100
committerLex Neva <github@lexneva.name>2017-09-24 01:56:53 +0100
commit41effdbf9f13c7d56cdf1acb027e4271d673ee51 (patch)
treed14d53a4673e817a3dd3d0f37d1a2a3f2f48c747 /embroider.py
parent60d14f777f56cfcf9c50b3b0be8e19e78e8ec532 (diff)
way easier satin column using additional subpaths to delineate sections
Diffstat (limited to 'embroider.py')
-rw-r--r--embroider.py41
1 files changed, 36 insertions, 5 deletions
diff --git a/embroider.py b/embroider.py
index ee9c4a24..5e0899b7 100644
--- a/embroider.py
+++ b/embroider.py
@@ -1225,6 +1225,39 @@ class SatinColumn(EmbroideryElement):
@property
@cache
def flattened_beziers(self):
+ if len(self.csp) == 2:
+ return self.simple_flatten_beziers()
+ else:
+ return self.flatten_beziers_with_rungs()
+
+
+ def flatten_beziers_with_rungs(self):
+ input_paths = [self.flatten([path]) for path in self.csp]
+ input_paths = [shgeo.LineString(path[0]) for path in input_paths]
+ input_paths.sort(key=lambda path: path.length, reverse=True)
+
+ # Imagine a satin column as a curvy ladder.
+ # The two long paths are the "rails" of the ladder. The remainder are
+ # the "rungs".
+ rails = input_paths[:2]
+ rungs = shgeo.MultiLineString(input_paths[2:])
+
+ result = []
+
+ for rail in rails:
+ # handle null intersections here?
+ linestrings = shapely.ops.split(rail, rungs)
+
+ if len(linestrings.geoms) < len(rungs) + 1:
+ raise Exception("Expected %d linestrings, got %d" % (len(rungs) + 1, len(linestrings.geoms)))
+
+ paths = [[PyEmb.Point(*coord) for coord in ls.coords] for ls in linestrings.geoms]
+ result.append(paths)
+
+ return zip(*result)
+
+
+ def simple_flatten_beziers(self):
# Given a pair of paths made up of bezier segments, flatten
# each individual bezier segment into line segments that approximate
# the curves. Retain the divisions between beziers -- we'll use those
@@ -1256,14 +1289,12 @@ class SatinColumn(EmbroideryElement):
node_id = self.node.get("id")
- if len(self.csp) != 2:
- self.fatal("satin column: object %s invalid: expected exactly two sub-paths, but there are %s" % (node_id, len(self.csp)))
-
if self.get_style("fill") is not None:
self.fatal("satin column: object %s has a fill (but should not)" % node_id)
- if len(self.csp[0]) != len(self.csp[1]):
- self.fatal("satin column: object %s has two paths with an unequal number of points (%s and %s)" % (node_id, len(self.csp[0]), len(self.csp[1])))
+ if len(self.csp) == 2:
+ if len(self.csp[0]) != len(self.csp[1]):
+ self.fatal("satin column: object %s has two paths with an unequal number of points (%s and %s)" % (node_id, len(self.csp[0]), len(self.csp[1])))
def offset_points(self, pos1, pos2, offset_px):
# Expand or contract two points about their midpoint. This is