summaryrefslogtreecommitdiff
path: root/lib/elements/auto_fill.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/elements/auto_fill.py')
-rw-r--r--lib/elements/auto_fill.py291
1 files changed, 0 insertions, 291 deletions
diff --git a/lib/elements/auto_fill.py b/lib/elements/auto_fill.py
deleted file mode 100644
index fbbd86d3..00000000
--- a/lib/elements/auto_fill.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# 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 math
-import sys
-import traceback
-
-from shapely import geometry as shgeo
-
-from .element import param
-from .fill import Fill
-from .validation import ValidationWarning
-from ..i18n import _
-from ..stitch_plan import StitchGroup
-from ..stitches import auto_fill
-from ..svg.tags import INKSCAPE_LABEL
-from ..utils import cache, version
-
-
-class SmallShapeWarning(ValidationWarning):
- name = _("Small Fill")
- description = _("This fill object is so small that it would probably look better as running stitch or satin column. "
- "For very small shapes, fill stitch is not possible, and Ink/Stitch will use running stitch around "
- "the outline instead.")
-
-
-class ExpandWarning(ValidationWarning):
- name = _("Expand")
- description = _("The expand parameter for this fill object cannot be applied. "
- "Ink/Stitch will ignore it and will use original size instead.")
-
-
-class UnderlayInsetWarning(ValidationWarning):
- name = _("Inset")
- description = _("The underlay inset parameter for this fill object cannot be applied. "
- "Ink/Stitch will ignore it and will use the original size instead.")
-
-
-class AutoFill(Fill):
- element_name = _("AutoFill")
-
- @property
- @param('auto_fill', _('Automatically routed fill stitching'), type='toggle', default=True)
- def auto_fill(self):
- return self.get_boolean_param('auto_fill', True)
-
- @property
- @cache
- def outline(self):
- return self.shape.boundary[0]
-
- @property
- @cache
- def outline_length(self):
- return self.outline.length
-
- @property
- def flip(self):
- return False
-
- @property
- @param('running_stitch_length_mm',
- _('Running stitch length (traversal between sections)'),
- tooltip=_('Length of stitches around the outline of the fill region used when moving from section to section.'),
- unit='mm',
- type='float',
- default=1.5)
- def running_stitch_length(self):
- return max(self.get_float_param("running_stitch_length_mm", 1.5), 0.01)
-
- @property
- @param('fill_underlay', _('Underlay'), type='toggle', group=_('AutoFill Underlay'), default=True)
- def fill_underlay(self):
- return self.get_boolean_param("fill_underlay", default=True)
-
- @property
- @param('fill_underlay_angle',
- _('Fill angle'),
- tooltip=_('Default: fill angle + 90 deg. Insert comma-seperated list for multiple layers.'),
- unit='deg',
- group=_('AutoFill Underlay'),
- type='float')
- @cache
- def fill_underlay_angle(self):
- underlay_angles = self.get_param('fill_underlay_angle', None)
- default_value = [self.angle + math.pi / 2.0]
- if underlay_angles is not None:
- underlay_angles = underlay_angles.strip().split(',')
- try:
- underlay_angles = [math.radians(float(angle)) for angle in underlay_angles]
- except (TypeError, ValueError):
- return default_value
- else:
- underlay_angles = default_value
-
- return underlay_angles
-
- @property
- @param('fill_underlay_row_spacing_mm',
- _('Row spacing'),
- tooltip=_('default: 3x fill row spacing'),
- unit='mm',
- group=_('AutoFill Underlay'),
- type='float')
- @cache
- def fill_underlay_row_spacing(self):
- return self.get_float_param("fill_underlay_row_spacing_mm") or self.row_spacing * 3
-
- @property
- @param('fill_underlay_max_stitch_length_mm',
- _('Max stitch length'),
- tooltip=_('default: equal to fill max stitch length'),
- unit='mm',
- group=_('AutoFill Underlay'), type='float')
- @cache
- def fill_underlay_max_stitch_length(self):
- return self.get_float_param("fill_underlay_max_stitch_length_mm") or self.max_stitch_length
-
- @property
- @param('fill_underlay_inset_mm',
- _('Inset'),
- tooltip=_('Shrink the shape before doing underlay, to prevent underlay from showing around the outside of the fill.'),
- unit='mm',
- group=_('AutoFill Underlay'),
- type='float',
- default=0)
- def fill_underlay_inset(self):
- return self.get_float_param('fill_underlay_inset_mm', 0)
-
- @property
- @param(
- 'fill_underlay_skip_last',
- _('Skip last stitch in each row'),
- tooltip=_('The last stitch in each row is quite close to the first stitch in the next row. '
- 'Skipping it decreases stitch count and density.'),
- group=_('AutoFill Underlay'),
- type='boolean',
- default=False)
- def fill_underlay_skip_last(self):
- return self.get_boolean_param("fill_underlay_skip_last", False)
-
- @property
- @param('expand_mm',
- _('Expand'),
- tooltip=_('Expand the shape before fill stitching, to compensate for gaps between shapes.'),
- unit='mm',
- type='float',
- default=0)
- def expand(self):
- return self.get_float_param('expand_mm', 0)
-
- @property
- @param('underpath',
- _('Underpath'),
- tooltip=_('Travel inside the shape when moving from section to section. Underpath '
- 'stitches avoid traveling in the direction of the row angle so that they '
- 'are not visible. This gives them a jagged appearance.'),
- type='boolean',
- default=True)
- def underpath(self):
- return self.get_boolean_param('underpath', True)
-
- @property
- @param(
- 'underlay_underpath',
- _('Underpath'),
- tooltip=_('Travel inside the shape when moving from section to section. Underpath '
- 'stitches avoid traveling in the direction of the row angle so that they '
- 'are not visible. This gives them a jagged appearance.'),
- group=_('AutoFill Underlay'),
- type='boolean',
- default=True)
- def underlay_underpath(self):
- return self.get_boolean_param('underlay_underpath', True)
-
- def shrink_or_grow_shape(self, amount, validate=False):
- if amount:
- shape = self.shape.buffer(amount)
- # changing the size can empty the shape
- # in this case we want to use the original shape rather than returning an error
- if shape.is_empty and not validate:
- return self.shape
- if not isinstance(shape, shgeo.MultiPolygon):
- shape = shgeo.MultiPolygon([shape])
- return shape
- else:
- return self.shape
-
- @property
- def underlay_shape(self):
- return self.shrink_or_grow_shape(-self.fill_underlay_inset)
-
- @property
- def fill_shape(self):
- return self.shrink_or_grow_shape(self.expand)
-
- def get_starting_point(self, last_patch):
- # If there is a "fill_start" Command, then use that; otherwise pick
- # the point closest to the end of the last patch.
-
- if self.get_command('fill_start'):
- return self.get_command('fill_start').target_point
- elif last_patch:
- return last_patch.stitches[-1]
- else:
- return None
-
- def get_ending_point(self):
- if self.get_command('fill_end'):
- return self.get_command('fill_end').target_point
- else:
- return None
-
- def to_stitch_groups(self, last_patch):
- stitch_groups = []
-
- starting_point = self.get_starting_point(last_patch)
- ending_point = self.get_ending_point()
-
- try:
- if self.fill_underlay:
- for i in range(len(self.fill_underlay_angle)):
- 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
- raise
-
- # for an uncaught exception, give a little more info so that they can create a bug report
- message = ""
- message += _("Error during autofill! This means that there is a problem with Ink/Stitch.")
- message += "\n\n"
- # L10N this message is followed by a URL: https://github.com/inkstitch/inkstitch/issues/new
- message += _("If you'd like to help us make Ink/Stitch better, please paste this whole message into a new issue at: ")
- message += "https://github.com/inkstitch/inkstitch/issues/new\n\n"
- message += version.get_inkstitch_version() + "\n\n"
- message += traceback.format_exc()
-
- self.fatal(message)
-
- 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)
-
- 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