summaryrefslogtreecommitdiff
path: root/lib/stitch_plan/stop.py
blob: 0ccaeaf8f15b5a72b10fce590a6ab49cb1da66b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
from copy import copy

from ..svg import PIXELS_PER_MM


def process_stop(stitch_plan):
    """Handle the "stop after" checkbox.

    The user wants the machine to pause after this patch.  This can
    be useful for applique and similar on multi-needle machines that
    normally would not stop between colors.

    In most machine embroidery file formats, there's no such thing as
    an actual "STOP" instruction.  All that exists is a "color change"
    command.

    On multi-needle machines, the user assigns needles to the colors in
    the design before starting stitching.  C01, C02, etc are the normal
    needles, but C00 is special.  For a block of stitches assigned
    to C00, the machine will continue sewing with the last color it
    had and pause after it completes the C00 block.  Machines that don't
    call it C00 still have a similar concept.

    We'll add a STOP instruction at the end of this color block.
    Unfortunately, we have a bit of a catch-22: the user needs to set
    C00 (or equivalent) for the _start_ of this block to get the
    machine to stop at the end of this block.  That means it will use
    the previous color, which isn't the right color at all!

    For the first STOP in a given thread color, we'll need to
    introduce an extra color change.  The user can then set the correct
    color for the first section and C00 for the second, resulting in
    a stop where we want it.

    We'll try to find a logical place to split the color block, like
    a TRIM or a really long stitch.  Failing that, we'll just split
    it in half.
    """

    color_block = stitch_plan.last_color_block

    if not color_block or len(color_block) < 2:
        return

    last_stitch = color_block.last_stitch
    color_block.add_stitch(stop=True)

    if len(stitch_plan) > 1:
        # if this isn't the first stop in this color, then we're done
        if stitch_plan.color_blocks[-2].stop_after and \
            stitch_plan.color_blocks[-2].color == color_block.color:
                return

    # We need to split this color block.  Pick the last TRIM or
    # the last long stitch (probably between distant patches).

    for i in xrange(len(color_block) - 2, -1, -1):
        stitch = color_block.stitches[i]

        if stitch.trim:
            # ignore the trim right before the stop we just added
            if i < len(color_block) - 2:
                # split after the trim
                i = i + 1
                break

        if i > 0:
            next_stitch = color_block.stitches[i + 1]

            if (stitch - next_stitch).length() > 20 * PIXELS_PER_MM:
                break

    if i == 0:
        # Darn, we didn't find a TRIM or long stitch.  Just chop the
        # block in half.
        i = len(color_block) / 2

    new_color_block = color_block.split_at(i)

    # If we're splitting in the middle of a run of stitches, we don't
    # want a gap to appear in the preview and the PDF printout, so
    # add an extra stitch to bridge the gap.  Technically this will
    # result in a double needle penetration but it's no big deal.
    if not color_block.last_stitch.trim:
        color_block.add_stitch(copy(new_color_block.stitches[0]))

    color_block.add_stitch(color_change=True, fake_color_change=True)
    stitch_plan.add_color_block(new_color_block)