From 52d9ee6a6d97b2ea752f5fdd3080a160a3574f82 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 30 Jun 2021 14:05:13 +0200 Subject: structuring --- lib/patterns.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 lib/patterns.py (limited to 'lib/patterns.py') diff --git a/lib/patterns.py b/lib/patterns.py new file mode 100644 index 00000000..8872a8ce --- /dev/null +++ b/lib/patterns.py @@ -0,0 +1,66 @@ +# Authors: see git history +# +# Copyright (c) 2010 Authors +# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +import inkex +from shapely import geometry as shgeo + +from .svg import apply_transforms +from .svg.tags import EMBROIDERABLE_TAGS +from .utils import Point + + +def is_pattern(node): + if node.tag not in EMBROIDERABLE_TAGS: + return False + return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') + + +def apply_patterns(patches, node): + patterns = _get_patterns(node) + if not patterns: + return patches + + patch_points = [] + for patch in patches: + for i, stitch in enumerate(patch.stitches): + patch_points.append(stitch) + if i == len(patch.stitches) - 1: + continue + intersection_points = _get_pattern_points(stitch, patch.stitches[i+1], patterns) + for point in intersection_points: + patch_points.append(point) + patch.stitches = patch_points + + +def _get_patterns(node): + xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" + patterns = node.xpath(xpath, namespaces=inkex.NSS) + line_strings = [] + for pattern in patterns: + if pattern.tag not in EMBROIDERABLE_TAGS: + continue + d = pattern.get_path() + path = inkex.paths.Path(d).to_superpath() + path = apply_transforms(path, pattern) + inkex.bezier.cspsubdiv(path, 0.1) + path = [[point for control_before, point, control_after in subpath] for subpath in path] + lines = [shgeo.LineString(p) for p in path] + for line in lines: + line_strings.append(line) + return shgeo.MultiLineString(line_strings) + + +def _get_pattern_points(first, second, patterns): + points = [] + for pattern in patterns: + intersection = shgeo.LineString([first, second]).intersection(pattern) + if isinstance(intersection, shgeo.Point): + points.append(Point(intersection.x, intersection.y)) + if isinstance(intersection, shgeo.MultiPoint): + for point in intersection: + points.append(Point(point.x, point.y)) + # sort points after their distance to left + points.sort(key=lambda point: point.distance(first)) + return points -- cgit v1.2.3 From a5d7ffaffd0b73b5848b7d55ea1f571ea94fd5a7 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Wed, 7 Jul 2021 20:07:04 +0200 Subject: add or remove stitches (stroke or fill) --- lib/patterns.py | 108 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 35 deletions(-) (limited to 'lib/patterns.py') diff --git a/lib/patterns.py b/lib/patterns.py index 8872a8ce..5ae763fc 100644 --- a/lib/patterns.py +++ b/lib/patterns.py @@ -5,8 +5,8 @@ import inkex from shapely import geometry as shgeo +import math -from .svg import apply_transforms from .svg.tags import EMBROIDERABLE_TAGS from .utils import Point @@ -14,53 +14,91 @@ from .utils import Point def is_pattern(node): if node.tag not in EMBROIDERABLE_TAGS: return False - return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '') + style = node.get('style') or '' + return "marker-start:url(#inkstitch-pattern-marker)" in style def apply_patterns(patches, node): patterns = _get_patterns(node) - if not patterns: - return patches + _apply_stroke_patterns(patterns['stroke_patterns'], patches) + _apply_fill_patterns(patterns['fill_patterns'], patches) - patch_points = [] - for patch in patches: - for i, stitch in enumerate(patch.stitches): - patch_points.append(stitch) - if i == len(patch.stitches) - 1: - continue - intersection_points = _get_pattern_points(stitch, patch.stitches[i+1], patterns) - for point in intersection_points: - patch_points.append(point) - patch.stitches = patch_points + +def _apply_stroke_patterns(patterns, patches): + for pattern in patterns: + for patch in patches: + patch_points = [] + for i, stitch in enumerate(patch.stitches): + patch_points.append(stitch) + if i == len(patch.stitches) - 1: + continue + intersection_points = _get_pattern_points(stitch, patch.stitches[i+1], pattern) + for point in intersection_points: + patch_points.append(point) + patch.stitches = patch_points + + +def _apply_fill_patterns(patterns, patches): + for pattern in patterns: + 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): + patch_points.append(stitch) + # keep start and end points + elif i - 1 < 0 or i >= len(patch.stitches) - 1: + 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: + patch_points.append(stitch) + patch.stitches = patch_points def _get_patterns(node): + from .elements import EmbroideryElement + from .elements.fill import Fill + from .elements.stroke import Stroke + + fills = [] + strokes = [] xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]" patterns = node.xpath(xpath, namespaces=inkex.NSS) - line_strings = [] for pattern in patterns: if pattern.tag not in EMBROIDERABLE_TAGS: continue - d = pattern.get_path() - path = inkex.paths.Path(d).to_superpath() - path = apply_transforms(path, pattern) - inkex.bezier.cspsubdiv(path, 0.1) - path = [[point for control_before, point, control_after in subpath] for subpath in path] - lines = [shgeo.LineString(p) for p in path] - for line in lines: - line_strings.append(line) - return shgeo.MultiLineString(line_strings) - - -def _get_pattern_points(first, second, patterns): + + element = EmbroideryElement(pattern) + fill = element.get_style('fill') + stroke = element.get_style('stroke') + + if fill is not None: + fill_pattern = Fill(pattern).shape + fills.append(fill_pattern) + + if stroke is not None: + stroke_pattern = Stroke(pattern).paths + line_strings = [shgeo.LineString(path) for path in stroke_pattern] + strokes.append(shgeo.MultiLineString(line_strings)) + + return {'fill_patterns': fills, 'stroke_patterns': strokes} + + +def _get_pattern_points(first, second, pattern): points = [] - for pattern in patterns: - intersection = shgeo.LineString([first, second]).intersection(pattern) - if isinstance(intersection, shgeo.Point): - points.append(Point(intersection.x, intersection.y)) - if isinstance(intersection, shgeo.MultiPoint): - for point in intersection: - points.append(Point(point.x, point.y)) - # sort points after their distance to left + intersection = shgeo.LineString([first, second]).intersection(pattern) + if isinstance(intersection, shgeo.Point): + points.append(Point(intersection.x, intersection.y)) + if isinstance(intersection, shgeo.MultiPoint): + for point in intersection: + points.append(Point(point.x, point.y)) + # sort points after their distance to first points.sort(key=lambda point: point.distance(first)) return points + + +def get_angle(a, b, c): + ang = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0])) + return ang + 360 if ang < 0 else ang -- cgit v1.2.3 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 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/patterns.py') 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 -- cgit v1.2.3 From d807b12870515e23bd9ac4f8ce024a3070de2805 Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Sun, 8 Aug 2021 21:51:29 +0200 Subject: remove get_angle --- lib/patterns.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'lib/patterns.py') diff --git a/lib/patterns.py b/lib/patterns.py index bb19f2b4..d282dc9c 100644 --- a/lib/patterns.py +++ b/lib/patterns.py @@ -3,8 +3,6 @@ # 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 @@ -46,7 +44,7 @@ def _apply_fill_patterns(patterns, patches): patch_points = [] for i, stitch in enumerate(patch.stitches): if not shgeo.Point(stitch).within(pattern): - # keep points outside the fill patter + # keep points outside the fill pattern patch_points.append(stitch) elif i - 1 < 0 or i >= len(patch.stitches) - 1: # keep start and end points @@ -97,8 +95,3 @@ def _get_pattern_points(first, second, pattern): # sort points after their distance to first points.sort(key=lambda point: point.distance(first)) return points - - -def get_angle(a, b, c): - ang = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0])) - return ang + 360 if ang < 0 else ang -- cgit v1.2.3 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/patterns.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/patterns.py') 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 -- cgit v1.2.3 From b49f7d28314f30727f9f963bddb795b88a95f2bd Mon Sep 17 00:00:00 2001 From: Kaalleen Date: Mon, 16 Aug 2021 16:30:22 +0200 Subject: keep satin column edges --- lib/patterns.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/patterns.py') diff --git a/lib/patterns.py b/lib/patterns.py index 70700f18..8a0c8449 100644 --- a/lib/patterns.py +++ b/lib/patterns.py @@ -58,6 +58,9 @@ def _apply_fill_patterns(patterns, patches): elif stitch.has_tag('auto_fill_travel'): # keep travel stitches (underpath or travel around the border) patch_points.append(stitch) + elif stitch.has_tag('satin_column') and not stitch.has_tag('satin_split_stitch'): + # keep satin column stitches unless they are split stitches + patch_points.append(stitch) patch.stitches = patch_points -- cgit v1.2.3