summaryrefslogtreecommitdiff
path: root/embroider.py
diff options
context:
space:
mode:
authorLex Neva <github@lexneva.name>2016-11-06 13:44:27 -0500
committerLex Neva <github@lexneva.name>2016-11-06 14:07:48 -0500
commite48a0f65565028f268761900515102134bee5008 (patch)
tree5d5e6426d30a4d365fc91589bd5f30e34d1f384e /embroider.py
parentb16f7de2fc69b9c8b131d5636950468ed345e902 (diff)
pick closest starting point
Diffstat (limited to 'embroider.py')
-rw-r--r--embroider.py103
1 files changed, 68 insertions, 35 deletions
diff --git a/embroider.py b/embroider.py
index 8dbe04e7..c9e112cf 100644
--- a/embroider.py
+++ b/embroider.py
@@ -311,7 +311,7 @@ class Fill(EmbroideryElement):
if shgeo.LineString(segment1).distance(shgeo.LineString(segment1)) > self.row_spacing * 1.1:
return False
- quad = make_quadrilateral(segment1, segment2)
+ quad = self.make_quadrilateral(segment1, segment2)
quad_area = quad.area
intersection_area = self.shape.intersection(quad).area
@@ -448,15 +448,17 @@ class Fill(EmbroideryElement):
class AutoFill(Fill):
+ def __init__(self, *args, **kwargs):
+ super(AutoFill, self).__init__(*args, **kwargs)
+
+ self.outline = self.shape.boundary[0]
+ self.outline_length = self.outline.length
+
@property
def flip(self):
return False
@property
- def outline(self):
- return self.shape.boundary[0]
-
- @property
def running_stitch_length(self):
return self.get_float_param("running_stitch_length_mm")
@@ -469,51 +471,82 @@ class AutoFill(Fill):
return True
- def get_corner_points(self, section):
- return section[0][0], section[0][-1], section[-1][0], section[-1][-1]
+ def perimeter_distance(self, p1, p2):
+ # how far around the perimeter (and in what direction) do I need to go
+ # to get from p1 to p2?
- def connect_points(self, p1, p2):
- p1 = shgeo.Point(p1)
- p2 = shgeo.Point(p2)
+ p1_projection = self.outline.project(shgeo.Point(p1))
+ p2_projection = self.outline.project(shgeo.Point(p2))
+
+ distance = p2_projection - p1_projection
+
+ if abs(distance) > self.outline_length / 2.0:
+ # if we'd have to go more than halfway around, it's faster to go
+ # the other way
+ if distance < 0:
+ return distance + self.outline_length
+ elif distance > 0:
+ return distance - self.outline_length
+ else:
+ # this ought not happen, but just for completeness, return 0 if
+ # p1 and p0 are the same point
+ return 0
+ else:
+ return distance
+ def connect_points(self, p1, p2):
patch = Patch(color=self.color)
- outline = self.outline
- outline_length = outline.length
- start = outline.project(p1)
- stitch_length = self.running_stitch_length
- stitches = int(outline.length / stitch_length)
+ pos = self.outline.project(shgeo.Point(p1))
+ distance = self.perimeter_distance(p1, p2)
+ stitches = abs(int(distance / self.running_stitch_length))
- # TODO: tidy this code up, make pull_runs split more aggressively to
- # completely avoid discontiguous sections, find the shorter direction
- # around the shape to the destination
+ direction = distance / abs(distance)
+ stitch = self.running_stitch_length * direction
for i in xrange(stitches):
- next_point = outline.interpolate((start + i * stitch_length) % outline_length)
- patch.add_stitch(PyEmb.Point(next_point.x, next_point.y))
-
- if next_point.distance(p2) <= stitch_length:
- break
+ pos = (pos + stitch) % self.outline_length
+
+ patch.add_stitch(PyEmb.Point(*self.outline.interpolate(pos).coords[0]))
return patch
+ def get_corner_points(self, section):
+ return section[0][0], section[0][-1], section[-1][0], section[-1][-1]
+
+ def nearest_corner(self, section, point):
+ return min(self.get_corner_points(section),
+ key=lambda corner: abs(self.perimeter_distance(point, corner)))
+
+ def find_nearest_section(self, sections, point):
+ sections_with_nearest_corner = [(i, self.nearest_corner(section, point))
+ for i, section in enumerate(sections)]
+ return min(sections_with_nearest_corner,
+ key=lambda(section, corner): abs(self.perimeter_distance(point, corner)))
+
+ def section_from_corner(self, section, start_corner):
+ if start_corner not in section[0]:
+ section = list(reversed(section))
+
+ if section[0][0] != start_corner:
+ section = [list(reversed(row)) for row in section]
+
+ return self.section_to_patch(section)
+
def to_patches(self):
rows_of_segments = self.intersect_region_with_grating()
sections = self.pull_runs(rows_of_segments)
- # to do: perhaps travel to the sections in a more intelligent manner, by
- # finding the next nearest corner point?
- #corner_points = [self.get_corner_points(section) for section in sections]
- print >> dbg, "autofill"
-
- patches = []
- last_section = None
- for section in sections:
- if last_section:
- patches.append(self.connect_points(patches[-1].stitches[-1], section[0][0]))
+ patches = []
+ while sections:
+ if patches:
+ last_stitch = patches[-1].stitches[-1]
+ section_index, start_corner = self.find_nearest_section(sections, last_stitch)
+ patches.append(self.connect_points(last_stitch, start_corner))
+ patches.append(self.section_from_corner(sections.pop(section_index), start_corner))
+ else:
+ patches.append(self.section_to_patch(sections.pop(0)))
- patches.append(self.section_to_patch(section))
- last_section = section
return patches