@@ -7,11 +7,103 @@ class EmbPattern:
77 def __init__ (self ):
88 self .stitches = [] # type: list
99 self .threadlist = [] # type: list
10- self .extras = {}
10+ self .extras = {} # type: dict
1111 # filename, name, category, author, keywords, comments, are typical
1212 self ._previousX = 0 # type: float
1313 self ._previousY = 0 # type: float
1414
15+ def __ne__ (self , other ):
16+ return not self .__eq__ (other )
17+
18+ def __eq__ (self , other ):
19+ if not isinstance (other , EmbPattern ):
20+ return False
21+ if self .stitches != other .stitches :
22+ return False
23+ if self .threadlist != other .threadlist :
24+ return False
25+ if self .extras != other .extras :
26+ return False
27+ return True
28+
29+ def __str__ (self ):
30+ if "name" in self .extras :
31+ return "EmbPattern %s (commands: %3d, threads: %3d)" % \
32+ (self .extras ["name" ], len (self .stitches ), len (self .threadlist ))
33+ return "EmbPattern (commands: %3d, threads: %3d)" % (len (self .stitches ), len (self .threadlist ))
34+
35+ def __len__ (self ):
36+ return len (self .stitches )
37+
38+ def __getitem__ (self , item ):
39+ if isinstance (item , str ):
40+ return self .extras [item ]
41+ return self .stitches [item ]
42+
43+ def __setitem__ (self , key , value ):
44+ if isinstance (key , str ):
45+ self .extras [key ] = value
46+ else :
47+ self .stitches [key ] = value
48+
49+ def __copy__ (self ):
50+ return self .copy ()
51+
52+ def __deepcopy__ (self ):
53+ return self .copy ()
54+
55+ def __iadd__ (self , other ):
56+ if isinstance (other , EmbPattern ):
57+ self .add_pattern (other )
58+ elif isinstance (other , EmbThread ) or isinstance (other , str ):
59+ self .add_thread (other )
60+ for i in range (0 , len (self .stitches )):
61+ data = self .stitches [i ][2 ] & COMMAND_MASK
62+ if data == STITCH or data == SEW_TO or data == NEEDLE_AT :
63+ self .color_change ()
64+ break # Only add color change if stitching exists.
65+ elif isinstance (other , int ):
66+ self .add_command (other )
67+ elif isinstance (other , list ) or isinstance (other , tuple ): # tuple or list
68+ if len (other ) == 0 :
69+ return
70+ v = other [0 ]
71+ if isinstance (v , list ) or isinstance (v , tuple ): # tuple or list of tuple or lists
72+ for v in other :
73+ x = v [0 ]
74+ y = v [1 ]
75+ try :
76+ cmd = v [2 ]
77+ except IndexError :
78+ cmd = STITCH
79+ self .add_stitch_absolute (cmd , x , y )
80+ elif isinstance (v , complex ): # tuple or list of complex
81+ for v in other :
82+ x = v .real
83+ y = v .imag
84+ self .add_stitch_absolute (STITCH , x , y )
85+ elif isinstance (v , int ) or isinstance (v , float ): # tuple or list of numbers.
86+ i = 0
87+ ie = len (other )
88+ while i < ie :
89+ self .add_stitch_absolute (STITCH , other [i ], other [i + 1 ])
90+ i += 2
91+ elif isinstance (v , str ):
92+ self .extras [v ] = other [1 ]
93+ else :
94+ raise ValueError ()
95+ return self
96+
97+ def __add__ (self , other ):
98+ p = self .copy ()
99+ p .add_pattern (other )
100+ return p
101+
102+ def __radd__ (self , other ):
103+ p = other .copy ()
104+ p .add_pattern (self )
105+ return p
106+
15107 def copy (self ):
16108 emb_pattern = EmbPattern ()
17109 emb_pattern .stitches = self .stitches [:]
@@ -238,7 +330,7 @@ def transform(self, matrix):
238330 matrix .apply (stitch )
239331
240332 def fix_color_count (self ):
241- """Ensure the there are threads for all color blocks."""
333+ """Ensure that there are threads for all color blocks."""
242334 thread_index = 0
243335 init_color = True
244336 for stitch in self .stitches :
@@ -321,6 +413,41 @@ def add_stitchblock(self, stitchblock):
321413 except AttributeError :
322414 self .add_stitch_absolute (stitch [2 ], stitch [0 ], stitch [1 ])
323415
416+ def add_pattern (self , pattern ):
417+ """
418+ add_pattern merges the given pattern with the current pattern. It accounts for some edge conditions but
419+ not all of them.
420+
421+ If there is an end command on the current pattern, that is removed.
422+ If the color ending the current pattern is equal to the color starting the next those color blocks are merged.
423+ Any prepended thread change command to the merging pattern is suppressed.
424+
425+ :param pattern: pattern to add to current pattern
426+ :return:
427+ """
428+ if self .stitches [- 1 ][2 ] == END :
429+ self .stitches = self .stitches [:- 1 ] # Remove END, if exists
430+
431+ # Add the new thread only if it's different from the last one
432+ self .fix_color_count ()
433+
434+ if len (pattern .threadlist ) > 0 :
435+ if pattern .threadlist [0 ] == self .threadlist [- 1 ]:
436+ self .threadlist .extend (pattern .threadlist [1 :])
437+ else :
438+ self .threadlist .extend (pattern .threadlist )
439+ self .color_change ()
440+ join_position = len (self .stitches )
441+ self .stitches .extend (pattern .stitches )
442+
443+ for i in range (join_position , len (self .stitches )):
444+ data = self .stitches [i ][2 ] & COMMAND_MASK
445+ if data == STITCH or data == SEW_TO or data == NEEDLE_AT :
446+ break
447+ elif data == COLOR_CHANGE or data == COLOR_BREAK or data == NEEDLE_SET :
448+ self .stitches [i ][2 ] = NO_COMMAND
449+ self .extras .update (pattern .extras )
450+
324451 def get_pattern_interpolate_trim (self , jumps_to_require_trim ):
325452 """Gets a processed pattern with untrimmed jumps merged
326453 and trims added if merged jumps are beyond the given value.
@@ -337,7 +464,7 @@ def get_pattern_interpolate_trim(self, jumps_to_require_trim):
337464 command = stitch [2 ] & COMMAND_MASK
338465 if command == STITCH or command == SEQUIN_EJECT :
339466 trimmed = False
340- elif command == COLOR_CHANGE or command == TRIM :
467+ elif command == COLOR_CHANGE or command == NEEDLE_SET or command == TRIM :
341468 trimmed = True
342469 if trimmed or stitch [2 ] != JUMP :
343470 new_pattern .add_stitch_absolute (stitch [2 ],
0 commit comments