@@ -271,6 +271,47 @@ def _get_stitch_commands(self) -> list[tuple[float, float, StitchCommand]]:
271
271
stitch_commands .extend (self ._iter_zigzag_between_positions (pos1 , pos2 ))
272
272
return stitch_commands
273
273
274
+ class SatinStitch (StitchGroup ):
275
+ """Stitch group for satin stitches.
276
+ Satin stitches create a dense, closely packed fill of stitches between two locations, similar to a zigzag stitch,
277
+ but with more closely spaced and finer stitch density.
278
+ Parameters
279
+ ----------
280
+ stitch_length : float
281
+ Distance between each satin stitch point.
282
+ amplitude : float
283
+ The distance from the central path to each side of the satin stitch.
284
+ density : float (optional, default=5.0)
285
+ Affects how closely packed the stitches are. Higher density means more stitches per unit of distance.
286
+ """
287
+ def __init__ (self , start_pos : Vec2D , stitch_length : float , amplitude : float , density : float = 5.0 ) -> None :
288
+ super ().__init__ (start_pos = start_pos )
289
+ self .stitch_length = stitch_length
290
+ self .amplitude = amplitude
291
+ self .density = density # Default density is higher for satin stitches (more closely packed)
292
+ def _iter_satin_between_positions (self , position_1 : Vec2D , position_2 : Vec2D ) -> Generator [tuple [float , float , StitchCommand ], None , None ]:
293
+ x1 , y1 = position_1
294
+ x2 , y2 = position_2
295
+ distance = math .sqrt ((x2 - x1 ) ** 2 + (y2 - y1 ) ** 2 )
296
+ angle = math .atan2 (y2 - y1 , x2 - x1 )
297
+ dx = math .cos (angle )
298
+ dy = math .sin (angle )
299
+ # Adjust stitch length based on density
300
+ effective_stitch_length = self .stitch_length / self .density
301
+ distance_traveled = 0
302
+ satin_side = - 1 # Start on one side of the line
303
+ while distance_traveled + effective_stitch_length <= distance :
304
+ x1 += effective_stitch_length * dx
305
+ y1 += effective_stitch_length * dy
306
+ distance_traveled += effective_stitch_length
307
+ # Calculate offset for satin pattern (smaller amplitude than zigzag)
308
+ offset_x = satin_side * self .amplitude * - dy # Perpendicular to the line
309
+ offset_y = satin_side * self .amplitude * dx
310
+ yield x1 + offset_x , y1 + offset_y , pyembroidery .STITCH
311
+ satin_side *= - 1 # Switch side
312
+ # Add the final point exactly at the end of the line
313
+ yield x2 , y2 , pyembroidery .STITCH
314
+
274
315
class JumpStitch (StitchGroup ):
275
316
"""Stitch group for jump stitches.
276
317
0 commit comments