summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/elements/element.py50
-rw-r--r--lib/elements/pattern.py7
-rw-r--r--lib/elements/utils.py3
-rw-r--r--lib/extensions/__init__.py4
-rw-r--r--lib/extensions/base.py2
-rw-r--r--lib/extensions/selection_to_pattern.py (renamed from lib/extensions/apply_pattern.py)3
-rw-r--r--lib/patterns.py66
7 files changed, 74 insertions, 61 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py
index aa0c4795..dc466fbf 100644
--- a/lib/elements/element.py
+++ b/lib/elements/element.py
@@ -9,10 +9,10 @@ from copy import deepcopy
import inkex
import tinycss2
from inkex import bezier
-from shapely import geometry as shgeo
from ..commands import find_commands
from ..i18n import _
+from ..patterns import apply_patterns
from ..svg import (PIXELS_PER_MM, apply_transforms, convert_length,
get_node_transform)
from ..svg.tags import (EMBROIDERABLE_TAGS, INKSCAPE_LABEL, INKSTITCH_ATTRIBS,
@@ -331,52 +331,6 @@ class EmbroideryElement(object):
else:
return None
- @cache
- def get_patterns(self):
- xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-pattern-marker)')]"
- patterns = self.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)
- path = self.flatten(path)
- lines = [shgeo.LineString(p) for p in path]
- for line in lines:
- line_strings.append(line)
- return shgeo.MultiLineString(line_strings)
-
- def _apply_patterns(self, patches):
- patterns = self.get_patterns()
- 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 = self._get_pattern_points(stitch, patch.stitches[i+1], patterns)
- for point in intersection_points:
- patch_points.append(point)
- patch.stitches = patch_points
-
- def _get_pattern_points(self, 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
-
def strip_control_points(self, subpath):
return [point for control_before, point, control_after in subpath]
@@ -409,7 +363,7 @@ class EmbroideryElement(object):
self.validate()
patches = self.to_patches(last_patch)
- self._apply_patterns(patches)
+ apply_patterns(patches, self.node)
for patch in patches:
patch.tie_modus = self.ties
diff --git a/lib/elements/pattern.py b/lib/elements/pattern.py
index fa54b7ba..98f29456 100644
--- a/lib/elements/pattern.py
+++ b/lib/elements/pattern.py
@@ -6,7 +6,6 @@
import inkex
from ..i18n import _
-from ..svg.tags import EMBROIDERABLE_TAGS
from .element import EmbroideryElement
from .validation import ObjectTypeWarning
@@ -31,9 +30,3 @@ class PatternObject(EmbroideryElement):
def to_patches(self, last_patch):
return []
-
-
-def is_pattern(node):
- if node.tag not in EMBROIDERABLE_TAGS:
- return False
- return "marker-start:url(#inkstitch-pattern-marker)" in node.get('style', '')
diff --git a/lib/elements/utils.py b/lib/elements/utils.py
index cd87cec8..99df7002 100644
--- a/lib/elements/utils.py
+++ b/lib/elements/utils.py
@@ -4,6 +4,7 @@
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from ..commands import is_command
+from ..patterns import is_pattern
from ..svg.tags import (EMBROIDERABLE_TAGS, SVG_IMAGE_TAG, SVG_PATH_TAG,
SVG_POLYLINE_TAG, SVG_TEXT_TAG)
from .auto_fill import AutoFill
@@ -12,7 +13,7 @@ from .element import EmbroideryElement
from .empty_d_object import EmptyDObject
from .fill import Fill
from .image import ImageObject
-from .pattern import PatternObject, is_pattern
+from .pattern import PatternObject
from .polyline import Polyline
from .satin_column import SatinColumn
from .stroke import Stroke
diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py
index 3bd2fef6..7996770d 100644
--- a/lib/extensions/__init__.py
+++ b/lib/extensions/__init__.py
@@ -5,7 +5,6 @@
from lib.extensions.troubleshoot import Troubleshoot
-from .apply_pattern import ApplyPattern
from .auto_satin import AutoSatin
from .break_apart import BreakApart
from .cleanup import Cleanup
@@ -29,6 +28,7 @@ from .params import Params
from .print_pdf import Print
from .remove_embroidery_settings import RemoveEmbroiderySettings
from .reorder import Reorder
+from .selection_to_pattern import SelectionToPattern
from .simulator import Simulator
from .stitch_plan_preview import StitchPlanPreview
from .zip import Zip
@@ -41,7 +41,7 @@ __all__ = extensions = [StitchPlanPreview,
Output,
Zip,
Flip,
- ApplyPattern,
+ SelectionToPattern,
ObjectCommands,
LayerCommands,
GlobalCommands,
diff --git a/lib/extensions/base.py b/lib/extensions/base.py
index 1c10cd4a..862d031e 100644
--- a/lib/extensions/base.py
+++ b/lib/extensions/base.py
@@ -15,8 +15,8 @@ from stringcase import snakecase
from ..commands import is_command, layer_commands
from ..elements import EmbroideryElement, nodes_to_elements
from ..elements.clone import is_clone
-from ..elements.pattern import is_pattern
from ..i18n import _
+from ..patterns import is_pattern
from ..svg import generate_unique_id
from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE,
NOT_EMBROIDERABLE_TAGS, SVG_DEFS_TAG, SVG_GROUP_TAG)
diff --git a/lib/extensions/apply_pattern.py b/lib/extensions/selection_to_pattern.py
index ad881604..3527cc5e 100644
--- a/lib/extensions/apply_pattern.py
+++ b/lib/extensions/selection_to_pattern.py
@@ -11,8 +11,7 @@ from ..svg.tags import SVG_DEFS_TAG
from .base import InkstitchExtension
-class ApplyPattern(InkstitchExtension):
- # This extension will mark selected
+class SelectionToPattern(InkstitchExtension):
def effect(self):
if not self.get_elements():
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