diff options
| author | Kaalleen <reni@allenka.de> | 2021-07-07 20:07:04 +0200 |
|---|---|---|
| committer | Kaalleen <reni@allenka.de> | 2021-07-07 20:07:04 +0200 |
| commit | a5d7ffaffd0b73b5848b7d55ea1f571ea94fd5a7 (patch) | |
| tree | 156651be37a733fa1ca8877ff26b5f8b59552e4c /lib/patterns.py | |
| parent | 736e10240a5c8357fac449371f8ac7451b7696b0 (diff) | |
add or remove stitches (stroke or fill)
Diffstat (limited to 'lib/patterns.py')
| -rw-r--r-- | lib/patterns.py | 108 |
1 files changed, 73 insertions, 35 deletions
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 |
