@@ -120,50 +120,83 @@ def clear(self):
120120 self ._previousX = 0
121121 self ._previousY = 0
122122
123- def move (self , dx = 0 , dy = 0 ):
123+ def move (self , dx = 0 , dy = 0 , position = None ):
124124 """Move dx, dy"""
125- self .add_stitch_relative (JUMP , dx , dy )
125+ if position is None :
126+ self .add_stitch_relative (JUMP , dx , dy )
127+ else :
128+ self .insert_stitch_relative (position , JUMP , dx , dy )
126129
127- def move_abs (self , x , y ):
130+ def move_abs (self , x , y , position = None ):
128131 """Move absolute x, y"""
129- self .add_stitch_absolute (JUMP , x , y )
132+ if position is None :
133+ self .add_stitch_absolute (JUMP , x , y )
134+ else :
135+ self .insert (position , JUMP , x , y )
130136
131- def stitch (self , dx = 0 , dy = 0 ):
137+ def stitch (self , dx = 0 , dy = 0 , position = None ):
132138 """Stitch dx, dy"""
133- self .add_stitch_relative (STITCH , dx , dy )
139+ if position is None :
140+ self .add_stitch_relative (STITCH , dx , dy )
141+ else :
142+ self .insert_stitch_relative (position , STITCH , dx , dy )
134143
135- def stitch_abs (self , x , y ):
144+ def stitch_abs (self , x , y , position = None ):
136145 """Stitch absolute x, y"""
137- self .add_stitch_absolute (STITCH , x , y )
146+ if position is None :
147+ self .add_stitch_absolute (STITCH , x , y )
148+ else :
149+ self .insert (position , STITCH , x , y )
138150
139- def stop (self , dx = 0 , dy = 0 ):
151+ def stop (self , dx = 0 , dy = 0 , position = None ):
140152 """Stop dx, dy"""
141- self .add_stitch_relative (STOP , dx , dy )
153+ if position is None :
154+ self .add_stitch_relative (STOP , dx , dy )
155+ else :
156+ self .insert_stitch_relative (position , STOP , dx , dy )
142157
143- def trim (self , dx = 0 , dy = 0 ):
158+ def trim (self , dx = 0 , dy = 0 , position = None ):
144159 """Trim dx, dy"""
145- self .add_stitch_relative (TRIM , dx , dy )
160+ if position is None :
161+ self .add_stitch_relative (TRIM , dx , dy )
162+ else :
163+ self .insert_stitch_relative (position , TRIM , dx , dy )
146164
147- def color_change (self , dx = 0 , dy = 0 ):
165+ def color_change (self , dx = 0 , dy = 0 , position = None ):
148166 """Color Change dx, dy"""
149- self .add_stitch_relative (COLOR_CHANGE , dx , dy )
167+ if position is None :
168+ self .add_stitch_relative (COLOR_CHANGE , dx , dy )
169+ else :
170+ self .insert_stitch_relative (position , COLOR_CHANGE , dx , dy )
150171
151- def needle_change (self , needle = 0 , dx = 0 , dy = 0 ):
172+ def needle_change (self , needle = 0 , dx = 0 , dy = 0 , position = None ):
152173 """Needle change, needle, dx, dy"""
153174 cmd = encode_thread_change (NEEDLE_SET , None , needle )
154- self .add_stitch_relative (cmd , dx , dy )
175+ if position is None :
176+ self .add_stitch_relative (cmd , dx , dy )
177+ else :
178+ self .insert_stitch_relative (position , cmd , dx , dy )
155179
156- def sequin_eject (self , dx = 0 , dy = 0 ):
180+ def sequin_eject (self , dx = 0 , dy = 0 , position = None ):
157181 """Eject Sequin dx, dy"""
158- self .add_stitch_relative (SEQUIN_EJECT , dx , dy )
182+ if position is None :
183+ self .add_stitch_relative (SEQUIN_EJECT , dx , dy )
184+ else :
185+ self .insert_stitch_relative (position , SEQUIN_EJECT , dx , dy )
159186
160- def sequin_mode (self , dx = 0 , dy = 0 ):
187+ def sequin_mode (self , dx = 0 , dy = 0 , position = None ):
161188 """Eject Sequin dx, dy"""
162- self .add_stitch_relative (SEQUIN_MODE , dx , dy )
189+ if position is None :
190+ self .add_stitch_relative (SEQUIN_MODE , dx , dy )
191+ else :
192+ self .insert_stitch_relative (position , SEQUIN_MODE , dx , dy )
163193
164- def end (self , dx = 0 , dy = 0 ):
194+ def end (self , dx = 0 , dy = 0 , position = None ):
165195 """End Design dx, dy"""
166- self .add_stitch_relative (END , dx , dy )
196+ if position is None :
197+ self .add_stitch_relative (END , dx , dy )
198+ else :
199+ self .insert_stitch_relative (position , END , dx , dy )
167200
168201 def add_thread (self , thread ):
169202 """Adds thread to design.
@@ -356,6 +389,26 @@ def add_stitch_relative(self, cmd, dx=0, dy=0):
356389 y = self ._previousY + dy
357390 self .add_stitch_absolute (cmd , x , y )
358391
392+ def insert_stitch_relative (self , position , cmd , dx = 0 , dy = 0 ):
393+ """Insert a relative stitch into the pattern. The stitch is relative to the stitch before it.
394+ If inserting at position 0, it's relative to 0,0. If appending, add is called, updating the positioning.
395+ """
396+ if position < 0 :
397+ position += len (self .stitches ) # I need positive positions.
398+ if position == 0 :
399+ self .stitches .insert (0 , [dx , dy , TRIM ]) # started (0,0)
400+ elif position == len (self .stitches ) or position is None : # This is properly just an add.
401+ self .add_stitch_relative (cmd , dx , dy )
402+ elif 0 < position < len (self .stitches ):
403+ p = self .stitches [position - 1 ]
404+ x = p [0 ] + dx
405+ y = p [1 ] + dy
406+ self .stitches .insert (position , [x , y , TRIM ])
407+
408+ def insert (self , position , cmd , x = 0 , y = 0 ):
409+ """Insert a stitch or command"""
410+ self .stitches .insert (position , [x , y , cmd ])
411+
359412 def prepend_command (self , cmd , x = 0 , y = 0 ):
360413 """Prepend a command, without treating parameters as locations"""
361414 self .stitches .insert (0 , [x , y , cmd ])
@@ -448,6 +501,60 @@ def add_pattern(self, pattern):
448501 self .stitches [i ][2 ] = NO_COMMAND
449502 self .extras .update (pattern .extras )
450503
504+ def interpolate_trims (self , jumps_to_require_trim = None , distance_to_require_trim = None , clipping = True ):
505+ """Processes a pattern adding trims according to the given criteria."""
506+ i = - 1
507+ ie = len (self .stitches ) - 1
508+
509+ x = 0
510+ y = 0
511+ jump_count = 0
512+ jump_start = 0
513+ jump_dx = 0
514+ jump_dy = 0
515+ jumping = False
516+ trimmed = True
517+ while i < ie :
518+ i += 1
519+ stitch = self .stitches [i ]
520+ dx = stitch [0 ] - x
521+ dy = stitch [1 ] - y
522+ x = stitch [0 ]
523+ y = stitch [1 ]
524+ command = stitch [2 ] & COMMAND_MASK
525+ if command == STITCH or command == SEQUIN_EJECT :
526+ trimmed = False
527+ jumping = False
528+ elif command == COLOR_CHANGE or command == NEEDLE_SET or command == TRIM :
529+ trimmed = True
530+ jumping = False
531+ if command == JUMP :
532+ if not jumping :
533+ jump_dx = 0
534+ jump_dy = 0
535+ jump_count = 0
536+ jump_start = i
537+ jumping = True
538+ jump_count += 1
539+ jump_dx += dx
540+ jump_dy += dy
541+ if not trimmed :
542+ if jump_count == jumps_to_require_trim or \
543+ distance_to_require_trim is not None and \
544+ (
545+ abs (jump_dy ) > distance_to_require_trim or \
546+ abs (jump_dx ) > distance_to_require_trim
547+ ):
548+ self .trim (position = jump_start )
549+ jump_start += 1 # We inserted a position, start jump has moved.
550+ i += 1
551+ ie += 1
552+ trimmed = True
553+ if clipping and jump_dx == 0 and jump_dy == 0 : # jump displacement is 0, clip trim command.
554+ del self .stitches [jump_start :i + 1 ]
555+ i = jump_start - 1
556+ ie = len (self .stitches ) - 1
557+
451558 def get_pattern_interpolate_trim (self , jumps_to_require_trim ):
452559 """Gets a processed pattern with untrimmed jumps merged
453560 and trims added if merged jumps are beyond the given value.
0 commit comments