Skip to content

Commit 1752f0d

Browse files
authored
Merge pull request #63 from EmbroidePy/tatarize-merge_and_builtins
Merge patterns and Builtins
2 parents 2f7ce87 + 17a5f29 commit 1752f0d

17 files changed

+292
-22
lines changed

pyembroidery/EmbMatrix.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,29 @@
22

33

44
class EmbMatrix:
5-
def __init__(self):
6-
self.m = self.get_identity()
5+
def __init__(self, m=None):
6+
if m is None:
7+
self.m = self.get_identity()
8+
else:
9+
self.m = m
10+
11+
def __ne__(self, other):
12+
return not self.__eq__(other)
13+
14+
def __eq__(self, other):
15+
return self.m == other.m
16+
17+
def __matmul__(self, other):
18+
return EmbMatrix(EmbMatrix.matrix_multiply(self.m, other.m))
19+
20+
def __rmatmul__(self, other):
21+
return EmbMatrix(EmbMatrix.matrix_multiply(self.m, other.m))
22+
23+
def __imatmul__(self, other):
24+
self.m = EmbMatrix.matrix_multiply(self.m, other.m)
25+
26+
def __str__(self):
27+
return "[%3f, %3f, %3f\n %3f, %3f, %3f\n %3f, %3f, %3f]" % self.m
728

829
def get_matrix(self):
930
return self.m

pyembroidery/EmbPattern.py

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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],

pyembroidery/EmbThread.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def color_distance_red_mean(
5555

5656
class EmbThread:
5757

58-
def __init__(self):
58+
def __init__(self, thread=None):
5959
self.color = 0xFF000000
6060
self.description = None # type: str
6161
self.catalog_number = None # type: str
@@ -64,6 +64,39 @@ def __init__(self):
6464
self.chart = None # type: str
6565
self.weight = None # type: str
6666
# description, catalog_number, details, brand, chart, weight
67+
if thread is not None:
68+
self.set(thread)
69+
70+
def __ne__(self, other):
71+
return not self.__eq__(other)
72+
73+
def __eq__(self, other):
74+
if other is None:
75+
return False
76+
if isinstance(other, int):
77+
return (0xFF000000 | self.color) == (0xFF000000 | other)
78+
if isinstance(other, str):
79+
return (0xFF000000 | self.color) == (0xFF000000 | EmbThread.parse_string_color(other))
80+
if not isinstance(other, EmbThread):
81+
return False
82+
if (0xFF000000 | self.color) != (0xFF000000 | other.color):
83+
return False
84+
if self.description != other.description:
85+
return False
86+
if self.catalog_number != other.description:
87+
return False
88+
if self.details != other.details:
89+
return False
90+
if self.brand != other.brand:
91+
return False
92+
if self.chart != other.chart:
93+
return False
94+
if self.weight != other.weight:
95+
return False
96+
return True
97+
98+
def __hash__(self):
99+
return self.color & 0xFFFFFF
67100

68101
def set_color(self, r, g, b):
69102
self.color = color_rgb(r, g, b)

pyembroidery/InbReader.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
def read_inb_stitches(f, out):
42
count = 0
53
while True:

pyembroidery/MitReader.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
MIT_SIZE_CONVERSION_RATIO = 2.0 / 1.0
32

43

pyembroidery/PcdReader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from .ReadHelper import read_int_8, read_int_24be, read_int_24le, read_int_16le, signed24
21
from .EmbThread import EmbThread
2+
from .ReadHelper import read_int_8, read_int_24be, read_int_24le, read_int_16le, signed24
33

44
PC_SIZE_CONVERSION_RATIO = 5.0 / 3.0
55

pyembroidery/PcqReader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from .ReadHelper import read_int_8, read_int_24be, read_int_24le, read_int_16le, signed24
21
from .EmbThread import EmbThread
2+
from .ReadHelper import read_int_8, read_int_24be, read_int_24le, read_int_16le, signed24
33

44
PC_SIZE_CONVERSION_RATIO = 5.0 / 3.0
55

pyembroidery/PcsReader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from .ReadHelper import read_int_8, read_int_24be, read_int_24le, read_int_16le, signed24
21
from .EmbThread import EmbThread
2+
from .ReadHelper import read_int_8, read_int_24be, read_int_24le, read_int_16le, signed24
33

44
PC_SIZE_CONVERSION_RATIO = 5.0 / 3.0
55

pyembroidery/PesWriter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from .PecWriter import write_pec
1+
from .EmbConstant import *
22
from .EmbThreadPec import get_thread_set
3+
from .PecWriter import write_pec
34
from .WriteHelper import write_string_utf8, write_int_32le, write_int_24le, write_int_16le, write_int_8, \
45
write_float_32le
5-
from .EmbConstant import *
66

77
SEQUIN_CONTINGENCY = CONTINGENCY_SEQUIN_JUMP
88
FULL_JUMP = True

pyembroidery/PhbReader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from .PecReader import read_pec_stitches
21
from .EmbThreadPec import get_thread_set
2+
from .PecReader import read_pec_stitches
33
from .ReadHelper import read_int_8, read_int_32le, read_int_16le
44

55

0 commit comments

Comments
 (0)