Skip to content

Commit 9576a22

Browse files
authored
Merge pull request #64 from EmbroidePy/tatarize-140
1.4.0 update
2 parents 1752f0d + 8752c81 commit 9576a22

26 files changed

+696
-172
lines changed

README.md

Lines changed: 73 additions & 57 deletions
Large diffs are not rendered by default.

__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
name = "pyembroidery"

pyembroidery/CsvWriter.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,21 @@ def write_stitches(pattern, f):
221221

222222

223223
def write(pattern, f, settings=None):
224-
deltas = settings is not None and "deltas" in settings
225-
displacement = settings is not None and "displacement" in settings
224+
version = "default"
225+
if settings is not None:
226+
if "deltas" in settings:
227+
version = "delta"
228+
elif "displacement" in settings:
229+
version = "full"
230+
version = settings.get("version", version)
226231
write_data(pattern, f)
227232
write_metadata(pattern, f)
228233
write_threads(pattern, f)
229234

230235
if len(pattern.stitches) > 0:
231-
if displacement:
236+
if version == "full":
232237
write_stitches_displacement(pattern, f)
233-
elif deltas:
238+
elif version == "delta":
234239
write_stitches_deltas(pattern, f)
235240
else:
236241
write_stitches(pattern, f)

pyembroidery/DstReader.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def dst_read_header(f, out):
5858
process_header_info(out, line[0:2].strip(), line[3:].strip())
5959

6060

61-
def dst_read_stitches(f, out):
61+
def dst_read_stitches(f, out, settings=None):
6262
sequin_mode = False
6363
while True:
6464
byte = bytearray(f.read(3))
@@ -67,7 +67,7 @@ def dst_read_stitches(f, out):
6767
dx = decode_dx(byte[0], byte[1], byte[2])
6868
dy = decode_dy(byte[0], byte[1], byte[2])
6969
if byte[2] & 0b11110011 == 0b11110011:
70-
out.end(dx, dy)
70+
break
7171
elif byte[2] & 0b11000011 == 0b11000011:
7272
out.color_change(dx, dy)
7373
elif byte[2] & 0b01000011 == 0b01000011:
@@ -80,8 +80,20 @@ def dst_read_stitches(f, out):
8080
out.move(dx, dy)
8181
else:
8282
out.stitch(dx, dy)
83+
out.end()
84+
85+
count_max = 3
86+
clipping = True
87+
trim_distance = None
88+
if settings is not None:
89+
count_max = settings.get('trim_at', count_max)
90+
trim_distance = settings.get("trim_distance", trim_distance)
91+
clipping = settings.get('clipping', clipping)
92+
if trim_distance is not None:
93+
trim_distance *= 10 # Pixels per mm. Native units are 1/10 mm.
94+
out.interpolate_trims(count_max, trim_distance, clipping)
8395

8496

8597
def read(f, out, settings=None):
8698
dst_read_header(f, out)
87-
dst_read_stitches(f, out)
99+
dst_read_stitches(f, out, settings)

pyembroidery/DstWriter.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,13 @@ def encode_record(x, y, flags):
102102

103103
def write(pattern, f, settings=None):
104104
extended_header = False
105+
trim_at = 3
105106
if settings is not None:
106-
extended_header = settings.get("extended header", extended_header)
107-
107+
extended_header = settings.get("extended header", extended_header) # deprecated, use version="extended"
108+
version = settings.get("version", "default")
109+
if version == "extended":
110+
extended_header = True
111+
trim_at = settings.get("trim_at", trim_at)
108112
bounds = pattern.bounds()
109113

110114
name = pattern.get_metadata("name", "Untitled")
@@ -164,8 +168,11 @@ def write(pattern, f, settings=None):
164168
xx += dx
165169
yy += dy
166170
if data == TRIM:
167-
f.write(encode_record(2, 2, JUMP))
168-
f.write(encode_record(-4, -4, JUMP))
169-
f.write(encode_record(2, 2, JUMP))
171+
delta = -4
172+
f.write(encode_record(-delta/2, -delta/2, JUMP))
173+
for p in range(1,trim_at-1):
174+
f.write(encode_record(delta, delta, JUMP))
175+
delta = -delta
176+
f.write(encode_record(delta/2, delta/2, JUMP))
170177
else:
171178
f.write(encode_record(dx, dy, data))

pyembroidery/EmbPattern.py

Lines changed: 129 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)