kopia lustrzana https://github.com/inkstitch/inkstitch
				
				
				
			refactor satin a bit
							rodzic
							
								
									de2cd9a30d
								
							
						
					
					
						commit
						afcd2d020a
					
				
							
								
								
									
										105
									
								
								embroider.py
								
								
								
								
							
							
						
						
									
										105
									
								
								embroider.py
								
								
								
								
							| 
						 | 
				
			
			@ -1241,7 +1241,10 @@ class Embroider(inkex.Effect):
 | 
			
		|||
        sortorder = self.get_sort_order(threadcolor, node)
 | 
			
		||||
        patch = Patch(color=threadcolor, sortorder=sortorder)
 | 
			
		||||
 | 
			
		||||
        def offset_stitches(pos1, pos2, offset_px):
 | 
			
		||||
        def offset_points(pos1, pos2, offset_px):
 | 
			
		||||
            # Expand or contract points.  This is useful for pull
 | 
			
		||||
            # compensation and insetting underlay.
 | 
			
		||||
 | 
			
		||||
            distance = (pos1 - pos2).length()
 | 
			
		||||
 | 
			
		||||
            if (pos1 - pos2).length() < 0.0001:
 | 
			
		||||
| 
						 | 
				
			
			@ -1249,7 +1252,8 @@ class Embroider(inkex.Effect):
 | 
			
		|||
                # to offset in, so we have to just return the points
 | 
			
		||||
                return pos1, pos2
 | 
			
		||||
 | 
			
		||||
            # don't offset so far that pos1 and pos2 switch places
 | 
			
		||||
            # if offset is negative, don't contract so far that pos1
 | 
			
		||||
            # and pos2 switch places
 | 
			
		||||
            if offset_px < -distance/2.0:
 | 
			
		||||
                offset_px = -distance/2.0 
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1259,22 +1263,20 @@ class Embroider(inkex.Effect):
 | 
			
		|||
    
 | 
			
		||||
            return pos1, pos2
 | 
			
		||||
    
 | 
			
		||||
        def calculate_satin(zigzag_spacing, offset):
 | 
			
		||||
            # Take each bezier segment in turn, drawing zigzags between the two
 | 
			
		||||
            # paths in that segment.
 | 
			
		||||
        def walk_paths(spacing, offset):
 | 
			
		||||
            # Take a bezier segment from each path in turn, and plot out an
 | 
			
		||||
            # equal number of points on each side.  Later code can alternate
 | 
			
		||||
            # between these points to create satin stitch, underlay, etc.
 | 
			
		||||
 | 
			
		||||
            # This code used to construct the Patch directly, but now it
 | 
			
		||||
            # returns the zig-zag stitches as two parallel lists (useful
 | 
			
		||||
            # for underlay)
 | 
			
		||||
            zigs = []
 | 
			
		||||
            zags = []
 | 
			
		||||
            side1 = []
 | 
			
		||||
            side2 = []
 | 
			
		||||
    
 | 
			
		||||
            def add_satin_stitch(pos1, pos2):
 | 
			
		||||
            def add_pair(pos1, pos2):
 | 
			
		||||
                # Stitches in satin tend to pull toward each other.  We can compensate
 | 
			
		||||
                # by spreading the points out.
 | 
			
		||||
                zig, zag = offset_stitches(pos1, pos2, offset)
 | 
			
		||||
                zigs.append(zig)
 | 
			
		||||
                zags.append(zag)
 | 
			
		||||
                pos1, pos2 = offset_points(pos1, pos2, offset)
 | 
			
		||||
                side1.append(pos1)
 | 
			
		||||
                side2.append(pos2)
 | 
			
		||||
    
 | 
			
		||||
            remainder_path1 = []
 | 
			
		||||
            remainder_path2 = []
 | 
			
		||||
| 
						 | 
				
			
			@ -1314,13 +1316,10 @@ class Embroider(inkex.Effect):
 | 
			
		|||
                # The risk here is that we poke a hole in the fabric if we try to
 | 
			
		||||
                # cram too many stitches on the short bezier.  The user will need
 | 
			
		||||
                # to avoid this through careful construction of paths.
 | 
			
		||||
                num_zigzags = max(len1, len2) / zigzag_spacing
 | 
			
		||||
                num_points = max(len1, len2) / spacing
 | 
			
		||||
    
 | 
			
		||||
                stitch_len1 = len1 / num_zigzags
 | 
			
		||||
                stitch_len2 = len2 / num_zigzags
 | 
			
		||||
    
 | 
			
		||||
                # Now do the stitches.  Each "zigzag" has a "zig" and a "zag", that
 | 
			
		||||
                # is, go from path1 to path2 and then back to path1.
 | 
			
		||||
                spacing1 = len1 / num_points
 | 
			
		||||
                spacing2 = len2 / num_points
 | 
			
		||||
    
 | 
			
		||||
                def walk(path, start_pos, start_index, distance):
 | 
			
		||||
                    # Move <distance> pixels along <path>'s line segments.
 | 
			
		||||
| 
						 | 
				
			
			@ -1360,13 +1359,11 @@ class Embroider(inkex.Effect):
 | 
			
		|||
    
 | 
			
		||||
    #            if num_zigzags >= 1.0:
 | 
			
		||||
    #                for stitch in xrange(int(num_zigzags) + 1):
 | 
			
		||||
                for stitch in xrange(int(num_zigzags)):
 | 
			
		||||
                    # In each iteration, do a "zig" (pos1) and a "zag" (pos2).
 | 
			
		||||
                for i in xrange(int(num_points)):
 | 
			
		||||
                    add_pair(pos1, pos2)
 | 
			
		||||
    
 | 
			
		||||
                    add_satin_stitch(pos1, pos2)
 | 
			
		||||
    
 | 
			
		||||
                    pos2, i2 = walk(subpath2, pos2, i2, stitch_len2)
 | 
			
		||||
                    pos1, i1 = walk(subpath1, pos1, i1, stitch_len1)
 | 
			
		||||
                    pos2, i2 = walk(subpath2, pos2, i2, spacing2)
 | 
			
		||||
                    pos1, i1 = walk(subpath1, pos1, i1, spacing1)
 | 
			
		||||
    
 | 
			
		||||
                if i1 < len(subpath1) - 1:
 | 
			
		||||
                    remainder_path1 = [pos1] + subpath1[i1 + 1:]
 | 
			
		||||
| 
						 | 
				
			
			@ -1382,39 +1379,58 @@ class Embroider(inkex.Effect):
 | 
			
		|||
                remainder_path2 = [p.as_tuple() for p in remainder_path2]
 | 
			
		||||
    
 | 
			
		||||
            # We're off by one in the algorithm above, so we need one more
 | 
			
		||||
            # pair of stitches.  We also want to stitch at the very end to
 | 
			
		||||
            # pair of points.  We also want to add points at the very end to
 | 
			
		||||
            # make sure we match the vectors on screen as best as possible.
 | 
			
		||||
            # Try to avoid doing both if they're going to stack up too
 | 
			
		||||
            # closely.
 | 
			
		||||
 
 | 
			
		||||
            end1 = PyEmb.Point(*remainder_path1[-1])
 | 
			
		||||
            end2 = PyEmb.Point(*remainder_path2[-1])
 | 
			
		||||
            if (end1 - pos1).length() > 0.3 * zigzag_spacing:
 | 
			
		||||
                add_satin_stitch(pos1, pos2)
 | 
			
		||||
            if (end1 - pos1).length() > 0.3 * spacing:
 | 
			
		||||
                add_pair(pos1, pos2)
 | 
			
		||||
 | 
			
		||||
            add_satin_stitch(end1, end2)
 | 
			
		||||
            add_pair(end1, end2)
 | 
			
		||||
 | 
			
		||||
            return [zigs, zags]
 | 
			
		||||
            return [side1, side2]
 | 
			
		||||
 | 
			
		||||
        def calculate_underlay(inset):
 | 
			
		||||
            forward, back = calculate_satin(underlay_stitch_len_px, -inset)
 | 
			
		||||
            # "contour walk" underlay: do stitches up one side and down the
 | 
			
		||||
            # other.
 | 
			
		||||
            forward, back = walk_paths(underlay_stitch_len_px, -inset)
 | 
			
		||||
            return Patch(color=threadcolor, sortorder=sortorder, stitches=(forward + list(reversed(back))))
 | 
			
		||||
 | 
			
		||||
        def satin_to_patch(zigzag_spacing, pull_compensation):
 | 
			
		||||
        def calculate_zigzag_underlay(zigzag_spacing, inset):
 | 
			
		||||
            # zigzag underlay, usually done at a much lower density than the
 | 
			
		||||
            # satin itself.  It looks like this:
 | 
			
		||||
            #
 | 
			
		||||
            # \/\/\/\/\/\/\/\/\/\/|
 | 
			
		||||
            # /\/\/\/\/\/\/\/\/\/\|
 | 
			
		||||
            #
 | 
			
		||||
            # In combination with the "contour walk" underlay, this is the
 | 
			
		||||
            # "German underlay" described here:
 | 
			
		||||
            #   http://www.mrxstitch.com/underlay-what-lies-beneath-machine-embroidery/
 | 
			
		||||
 | 
			
		||||
            patch = Patch(color=threadcolor, sortorder=sortorder)
 | 
			
		||||
 | 
			
		||||
            sides = calculate_satin(zigzag_spacing, pull_compensation)
 | 
			
		||||
            sides = walk_paths(zigzag_spacing/2.0, -inset)
 | 
			
		||||
            sides = [sides[0][::2] + list(reversed(sides[0][1::2])), sides[1][1::2] + list(reversed(sides[1][::2]))] 
 | 
			
		||||
 | 
			
		||||
            # this fancy bit of iterable magic just repeatedly takes a point
 | 
			
		||||
            # from each list in turn
 | 
			
		||||
            for point in chain.from_iterable(izip(*sides)):
 | 
			
		||||
                patch.addStitch(point)
 | 
			
		||||
 | 
			
		||||
            return patch
 | 
			
		||||
 | 
			
		||||
        def do_zigzag_underlay(zigzag_spacing, inset):
 | 
			
		||||
        def calculate_satin(zigzag_spacing, pull_compensation):
 | 
			
		||||
            # satin: do a zigzag pattern, alternating between the paths.  The
 | 
			
		||||
            # zigzag looks like this:
 | 
			
		||||
            #
 | 
			
		||||
            # /|/|/|/|/|/|/|/|
 | 
			
		||||
 | 
			
		||||
            patch = Patch(color=threadcolor, sortorder=sortorder)
 | 
			
		||||
 | 
			
		||||
            sides = calculate_satin(zigzag_spacing/2.0, -inset)
 | 
			
		||||
            sides = [sides[0][::2] + list(reversed(sides[0][1::2])), sides[1][1::2] + list(reversed(sides[1][::2]))] 
 | 
			
		||||
            sides = walk_paths(zigzag_spacing, pull_compensation)
 | 
			
		||||
 | 
			
		||||
            for point in chain.from_iterable(izip(*sides)):
 | 
			
		||||
                patch.addStitch(point)
 | 
			
		||||
| 
						 | 
				
			
			@ -1422,16 +1438,25 @@ class Embroider(inkex.Effect):
 | 
			
		|||
            return patch
 | 
			
		||||
 | 
			
		||||
        if center_walk:
 | 
			
		||||
            # inset will be clamped to the center point between the stitches
 | 
			
		||||
            # Center walk is a running stitch exactly between the paths, down
 | 
			
		||||
            # and back.  It comes first.
 | 
			
		||||
 | 
			
		||||
            # Bit of a hack: do it just like contour walk underlay but inset it
 | 
			
		||||
            # really far.  The inset will be clamped to the center between the
 | 
			
		||||
            # paths.
 | 
			
		||||
            patch += calculate_underlay(10000)
 | 
			
		||||
 | 
			
		||||
        if underlay:
 | 
			
		||||
            # Now do the contour walk underlay.
 | 
			
		||||
            patch += calculate_underlay(underlay_inset)
 | 
			
		||||
 | 
			
		||||
        if zigzag_underlay_spacing:
 | 
			
		||||
            patch += do_zigzag_underlay(zigzag_underlay_spacing, zigzag_underlay_inset)
 | 
			
		||||
            # zigzag underlay comes after contour walk underlay, so that the
 | 
			
		||||
            # zigzags sit on the contour walk underlay like rail ties on rails.
 | 
			
		||||
            patch += calculate_zigzag_underlay(zigzag_underlay_spacing, zigzag_underlay_inset)
 | 
			
		||||
 | 
			
		||||
        patch += satin_to_patch(zigzag_spacing_px, pull_compensation_px)
 | 
			
		||||
        # Finally, add the satin itself.
 | 
			
		||||
        patch += calculate_satin(zigzag_spacing_px, pull_compensation_px)
 | 
			
		||||
 | 
			
		||||
        return [patch]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue