diff options
Diffstat (limited to 'lib/stitches/running_stitch.py')
| -rw-r--r-- | lib/stitches/running_stitch.py | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/lib/stitches/running_stitch.py b/lib/stitches/running_stitch.py new file mode 100644 index 00000000..81124339 --- /dev/null +++ b/lib/stitches/running_stitch.py @@ -0,0 +1,66 @@ +""" Utility functions to produce running stitches. """ + + +def running_stitch(points, stitch_length): + """Generate running stitch along a path. + + Given a path and a stitch length, walk along the path in increments of the + stitch length. If sharp corners are encountered, an extra stitch will be + added at the corner to avoid rounding the corner. The starting and ending + point are always stitched. + + The path is described by a set of line segments, each connected to the next. + The line segments are described by a sequence of points. + """ + + if len(points) < 2: + return [] + + output = [points[0]] + segment_start = points[0] + last_segment_direction = None + + # This tracks the distance we've travelled along the current segment so + # far. Each time we make a stitch, we add the stitch_length to this + # value. If we fall off the end of the current segment, we carry over + # the remainder to the next segment. + distance = 0.0 + + for segment_end in points[1:]: + segment = segment_end - segment_start + segment_length = segment.length() + + if segment_length == 0: + continue + + segment_direction = segment.unit() + + # corner detection + if last_segment_direction: + cos_angle_between = segment_direction * last_segment_direction + + # This checks whether the corner is sharper than 45 degrees. + if cos_angle_between < 0.5: + # Only add the corner point if it's more than 0.1mm away to + # avoid a double-stitch. + if (segment_start - output[-1]).length() > 0.1: + # add a stitch at the corner + output.append(segment_start) + + # next stitch needs to be stitch_length along this segment + distance = stitch_length + + while distance < segment_length: + output.append(segment_start + distance * segment_direction) + distance += stitch_length + + # prepare for the next segment + segment_start = segment_end + last_segment_direction = segment_direction + distance -= segment_length + + # stitch the last point unless we're already almos there + if (segment_start - points[-1]).length() > 0.1: + output.append(segment_start) + + return output |
