From b1af926ea6018b869d2401aeece46318b88d9a5d Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 7 Aug 2021 12:34:07 -0400 Subject: add tags to fill stitches --- lib/stitches/fill.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/stitches') diff --git a/lib/stitches/fill.py b/lib/stitches/fill.py index 5aead9c7..0ac15657 100644 --- a/lib/stitches/fill.py +++ b/lib/stitches/fill.py @@ -7,6 +7,7 @@ import math import shapely +from ..stitch_plan import Stitch from ..svg import PIXELS_PER_MM from ..utils import Point as InkstitchPoint from ..utils import cache @@ -65,8 +66,8 @@ def stitch_row(stitches, beg, end, angle, row_spacing, max_stitch_length, stagge # tile with each other. That's important because we often get # abutting fill regions from pull_runs(). - beg = InkstitchPoint(*beg) - end = InkstitchPoint(*end) + beg = Stitch(*beg, tags=('fill_row_start',)) + end = Stitch(*end, tags=('fill_row_end')) row_direction = (end - beg).unit() segment_length = (end - beg).length() @@ -85,11 +86,13 @@ def stitch_row(stitches, beg, end, angle, row_spacing, max_stitch_length, stagge offset = (first_stitch - beg).length() while offset < segment_length: - stitches.append(beg + offset * row_direction) + stitches.append(Stitch(beg + offset * row_direction, tags=('fill_row'))) offset += max_stitch_length if (end - stitches[-1]).length() > 0.1 * PIXELS_PER_MM and not skip_last: stitches.append(end) + else: + stitches[-1].add_tag('fill_row_end') def intersect_region_with_grating(shape, angle, row_spacing, end_row_spacing=None, flip=False): -- cgit v1.3.1 From b411305c6742ff07dbddbdec07f1338f5beaf31b Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sat, 7 Aug 2021 18:38:57 -0400 Subject: use tags to decide which stitches to keep --- lib/patterns.py | 16 ++++++++-------- lib/stitches/fill.py | 9 ++------- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'lib/stitches') diff --git a/lib/patterns.py b/lib/patterns.py index 5ae763fc..bb19f2b4 100644 --- a/lib/patterns.py +++ b/lib/patterns.py @@ -3,10 +3,12 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. +import math + import inkex from shapely import geometry as shgeo -import math +from .stitch_plan import Stitch from .svg.tags import EMBROIDERABLE_TAGS from .utils import Point @@ -34,7 +36,7 @@ def _apply_stroke_patterns(patterns, patches): continue intersection_points = _get_pattern_points(stitch, patch.stitches[i+1], pattern) for point in intersection_points: - patch_points.append(point) + patch_points.append(Stitch(point, tags=('pattern_point',))) patch.stitches = patch_points @@ -43,16 +45,14 @@ def _apply_fill_patterns(patterns, patches): for patch in patches: patch_points = [] for i, stitch in enumerate(patch.stitches): - # keep points outside the fill patter if not shgeo.Point(stitch).within(pattern): + # keep points outside the fill patter patch_points.append(stitch) - # keep start and end points elif i - 1 < 0 or i >= len(patch.stitches) - 1: + # keep start and end points patch_points.append(stitch) - # keep points if they have an angle - # the necessary angle can be variable with certain stitch types (later on) - # but they don't need to use filled patterns for those - elif not 179 < get_angle(patch.stitches[i-1], stitch, patch.stitches[i+1]) < 181: + elif stitch.has_tag('fill_row_start') or stitch.has_tag('fill_row_end'): + # keep points if they are the start or end of a fill stitch row patch_points.append(stitch) patch.stitches = patch_points diff --git a/lib/stitches/fill.py b/lib/stitches/fill.py index 0ac15657..d134be32 100644 --- a/lib/stitches/fill.py +++ b/lib/stitches/fill.py @@ -67,15 +67,12 @@ def stitch_row(stitches, beg, end, angle, row_spacing, max_stitch_length, stagge # abutting fill regions from pull_runs(). beg = Stitch(*beg, tags=('fill_row_start',)) - end = Stitch(*end, tags=('fill_row_end')) + end = Stitch(*end, tags=('fill_row_end',)) row_direction = (end - beg).unit() segment_length = (end - beg).length() - # only stitch the first point if it's a reasonable distance away from the - # last stitch - if not stitches or (beg - stitches[-1]).length() > 0.5 * PIXELS_PER_MM: - stitches.append(beg) + stitches.append(beg) first_stitch = adjust_stagger(beg, angle, row_spacing, max_stitch_length, staggers) @@ -91,8 +88,6 @@ def stitch_row(stitches, beg, end, angle, row_spacing, max_stitch_length, stagge if (end - stitches[-1]).length() > 0.1 * PIXELS_PER_MM and not skip_last: stitches.append(end) - else: - stitches[-1].add_tag('fill_row_end') def intersect_region_with_grating(shape, angle, row_spacing, end_row_spacing=None, flip=False): -- cgit v1.3.1 From dd865008356d1e04b29a5eb59a8480900f255628 Mon Sep 17 00:00:00 2001 From: Lex Neva Date: Sun, 15 Aug 2021 17:24:59 -0400 Subject: keep underlay, underpath, and border travel --- lib/elements/auto_fill.py | 82 +++++++++++++++++++++++------------------ lib/patterns.py | 6 +++ lib/stitch_plan/stitch_group.py | 13 ++++++- lib/stitches/auto_fill.py | 8 +++- 4 files changed, 71 insertions(+), 38 deletions(-) (limited to 'lib/stitches') diff --git a/lib/elements/auto_fill.py b/lib/elements/auto_fill.py index f5558cbb..fbbd86d3 100644 --- a/lib/elements/auto_fill.py +++ b/lib/elements/auto_fill.py @@ -214,7 +214,7 @@ class AutoFill(Fill): return None def to_stitch_groups(self, last_patch): - stitches = [] + stitch_groups = [] starting_point = self.get_starting_point(last_patch) ending_point = self.get_ending_point() @@ -222,29 +222,40 @@ class AutoFill(Fill): try: if self.fill_underlay: for i in range(len(self.fill_underlay_angle)): - stitches.extend(auto_fill(self.underlay_shape, - self.fill_underlay_angle[i], - self.fill_underlay_row_spacing, - self.fill_underlay_row_spacing, - self.fill_underlay_max_stitch_length, - self.running_stitch_length, - self.staggers, - self.fill_underlay_skip_last, - starting_point, - underpath=self.underlay_underpath)) - starting_point = stitches[-1] - - stitches.extend(auto_fill(self.fill_shape, - self.angle, - self.row_spacing, - self.end_row_spacing, - self.max_stitch_length, - self.running_stitch_length, - self.staggers, - self.skip_last, - starting_point, - ending_point, - self.underpath)) + underlay = StitchGroup( + color=self.color, + tags=("auto_fill", "auto_fill_underlay"), + stitches=auto_fill( + self.underlay_shape, + self.fill_underlay_angle[i], + self.fill_underlay_row_spacing, + self.fill_underlay_row_spacing, + self.fill_underlay_max_stitch_length, + self.running_stitch_length, + self.staggers, + self.fill_underlay_skip_last, + starting_point, + underpath=self.underlay_underpath)) + stitch_groups.append(underlay) + + starting_point = underlay.stitches[-1] + + stitch_group = StitchGroup( + color=self.color, + tags=("auto_fill", "auto_fill_top"), + stitches=auto_fill( + self.fill_shape, + self.angle, + self.row_spacing, + self.end_row_spacing, + self.max_stitch_length, + self.running_stitch_length, + self.staggers, + self.skip_last, + starting_point, + ending_point, + self.underpath)) + stitch_groups.append(stitch_group) except Exception: if hasattr(sys, 'gettrace') and sys.gettrace(): # if we're debugging, let the exception bubble up @@ -262,18 +273,19 @@ class AutoFill(Fill): self.fatal(message) - return [StitchGroup(stitches=stitches, color=self.color)] + return stitch_groups - def validation_warnings(self): - if self.shape.area < 20: - label = self.node.get(INKSCAPE_LABEL) or self.node.get("id") - yield SmallShapeWarning(self.shape.centroid, label) - if self.shrink_or_grow_shape(self.expand, True).is_empty: - yield ExpandWarning(self.shape.centroid) +def validation_warnings(self): + if self.shape.area < 20: + label = self.node.get(INKSCAPE_LABEL) or self.node.get("id") + yield SmallShapeWarning(self.shape.centroid, label) - if self.shrink_or_grow_shape(-self.fill_underlay_inset, True).is_empty: - yield UnderlayInsetWarning(self.shape.centroid) + if self.shrink_or_grow_shape(self.expand, True).is_empty: + yield ExpandWarning(self.shape.centroid) - for warning in super(AutoFill, self).validation_warnings(): - yield warning + if self.shrink_or_grow_shape(-self.fill_underlay_inset, True).is_empty: + yield UnderlayInsetWarning(self.shape.centroid) + + for warning in super(AutoFill, self).validation_warnings(): + yield warning diff --git a/lib/patterns.py b/lib/patterns.py index d282dc9c..70700f18 100644 --- a/lib/patterns.py +++ b/lib/patterns.py @@ -52,6 +52,12 @@ def _apply_fill_patterns(patterns, patches): elif stitch.has_tag('fill_row_start') or stitch.has_tag('fill_row_end'): # keep points if they are the start or end of a fill stitch row patch_points.append(stitch) + elif stitch.has_tag('auto_fill') and not stitch.has_tag('auto_fill_top'): + # keep auto-fill underlay + patch_points.append(stitch) + elif stitch.has_tag('auto_fill_travel'): + # keep travel stitches (underpath or travel around the border) + patch_points.append(stitch) patch.stitches = patch_points diff --git a/lib/stitch_plan/stitch_group.py b/lib/stitch_plan/stitch_group.py index ee077f26..98d9799e 100644 --- a/lib/stitch_plan/stitch_group.py +++ b/lib/stitch_plan/stitch_group.py @@ -17,7 +17,7 @@ class StitchGroup: between them by the stitch plan generation code. """ - def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, tie_modus=0, stitch_as_is=False): + def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, tie_modus=0, stitch_as_is=False, tags=None): self.color = color self.trim_after = trim_after self.stop_after = stop_after @@ -28,6 +28,9 @@ class StitchGroup: if stitches: self.add_stitches(stitches) + if tags: + self.add_tags(tags) + def __add__(self, other): if isinstance(other, StitchGroup): return StitchGroup(self.color, self.stitches + other.stitches) @@ -51,3 +54,11 @@ class StitchGroup: def reverse(self): return StitchGroup(self.color, self.stitches[::-1]) + + def add_tags(self, tags): + for stitch in self.stitches: + stitch.add_tags(tags) + + def add_tag(self, tag): + for stitch in self.stitches: + stitch.add_tag(tag) diff --git a/lib/stitches/auto_fill.py b/lib/stitches/auto_fill.py index 07361f13..160d927e 100644 --- a/lib/stitches/auto_fill.py +++ b/lib/stitches/auto_fill.py @@ -14,6 +14,7 @@ from shapely.ops import snap from shapely.strtree import STRtree from ..debug import debug +from ..stitch_plan import Stitch from ..svg import PIXELS_PER_MM from ..utils.geometry import Point as InkstitchPoint from ..utils.geometry import line_string_to_point_list @@ -592,9 +593,12 @@ def travel(travel_graph, start, end, running_stitch_length, skip_last): """Create stitches to get from one point on an outline of the shape to another.""" path = networkx.shortest_path(travel_graph, start, end, weight='weight') - path = [InkstitchPoint(*p) for p in path] + path = [Stitch(*p) for p in path] stitches = running_stitch(path, running_stitch_length) + for stitch in stitches: + stitch.add_tag('auto_fill_travel') + # The path's first stitch will start at the end of a row of stitches. We # don't want to double that last stitch, so we'd like to skip it. if skip_last and len(path) > 2: @@ -619,7 +623,7 @@ def path_to_stitches(path, travel_graph, fill_stitch_graph, angle, row_spacing, # If the very first stitch is travel, we'll omit it in travel(), so add it here. if not path[0].is_segment(): - stitches.append(InkstitchPoint(*path[0].nodes[0])) + stitches.append(Stitch(*path[0].nodes[0])) for edge in path: if edge.is_segment(): -- cgit v1.3.1