summaryrefslogtreecommitdiff
path: root/lib/patterns.py
diff options
context:
space:
mode:
authorKaalleen <reni@allenka.de>2021-07-07 20:07:04 +0200
committerKaalleen <reni@allenka.de>2021-07-07 20:07:04 +0200
commita5d7ffaffd0b73b5848b7d55ea1f571ea94fd5a7 (patch)
tree156651be37a733fa1ca8877ff26b5f8b59552e4c /lib/patterns.py
parent736e10240a5c8357fac449371f8ac7451b7696b0 (diff)
add or remove stitches (stroke or fill)
Diffstat (limited to 'lib/patterns.py')
-rw-r--r--lib/patterns.py108
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