Undo stitch plan preview and density map (#1687)

pull/1701/head
Kaalleen 2022-06-21 19:48:28 +02:00 zatwierdzone przez GitHub
rodzic edacc3ec77
commit eef2ec232e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
9 zmienionych plików z 251 dodań i 17 usunięć

Wyświetl plik

@ -15,6 +15,7 @@ from .convert_to_satin import ConvertToSatin
from .convert_to_stroke import ConvertToStroke
from .cut_satin import CutSatin
from .cutwork_segmentation import CutworkSegmentation
from .density_map import DensityMap
from .duplicate_params import DuplicateParams
from .embroider_settings import EmbroiderSettings
from .flip import Flip
@ -39,13 +40,16 @@ 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 .selection_to_guide_line import SelectionToGuideLine
from .selection_to_pattern import SelectionToPattern
from .simulator import Simulator
from .stitch_plan_preview import StitchPlanPreview
from .stitch_plan_preview_undo import StitchPlanPreviewUndo
from .zip import Zip
__all__ = extensions = [StitchPlanPreview,
StitchPlanPreviewUndo,
DensityMap,
Install,
Params,
Print,

Wyświetl plik

@ -0,0 +1,142 @@
# 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 numpy as np
from scipy.spatial import KDTree
import inkex
from ..i18n import _
from ..stitch_plan import stitch_groups_to_stitch_plan
from ..svg import PIXELS_PER_MM
from ..svg.tags import INKSCAPE_GROUPMODE, INKSCAPE_LABEL, SVG_GROUP_TAG
from ..svg.units import get_viewbox_transform
from ..utils import cache
from .base import InkstitchExtension
class DensityMap(InkstitchExtension):
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self, *args, **kwargs)
self.arg_parser.add_argument("-v", "--layer-visibility", type=int, default=0, dest="layer_visibility")
self.arg_parser.add_argument("-l", "--num-neighbors-red", type=int, default=6, dest="num_neighbors_red")
self.arg_parser.add_argument("-r", "--density-radius-red", type=float, default=0.5, dest="radius_red")
self.arg_parser.add_argument("-m", "--num-neighbors-yellow", type=int, default=3, dest="num_neighbors_yellow")
self.arg_parser.add_argument("-s", "--density-radius-yellow", type=float, default=0.5, dest="radius_yellow")
def effect(self):
# delete old stitch plan
svg = self.document.getroot()
reset_density_plan(svg)
# create new stitch plan
if not self.get_elements():
return
self.metadata = self.get_inkstitch_metadata()
collapse_len = self.metadata['collapse_len_mm']
patches = self.elements_to_stitch_groups(self.elements)
stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len)
layer = svg.find(".//*[@id='__inkstitch_density_plan__']")
color_groups = create_color_groups(layer)
density_options = [{'max_neighbors': self.options.num_neighbors_red, 'radius': self.options.radius_red},
{'max_neighbors': self.options.num_neighbors_yellow, 'radius': self.options.radius_yellow}]
color_block_to_density_markers(svg, color_groups, stitch_plan, density_options)
# update layer visibility 0 = unchanged, 1 = hidden, 2 = lower opacity
groups = self.document.getroot().findall(SVG_GROUP_TAG)
if self.options.layer_visibility == 1:
self.hide_all_layers()
layer.style['display'] = "inline"
elif self.options.layer_visibility == 2:
for g in groups:
style = g.specified_style()
# check groupmode and exclude density layer
# exclude objects which are not displayed at all or already have opacity < 0.4
if (g.get(INKSCAPE_GROUPMODE) == "layer" and not g == layer and
float(style.get('opacity', 1)) > 0.4 and not style.get('display', 'inline') == 'none'):
g.style['opacity'] = 0.4
def reset_density_plan(svg):
layer = svg.find(".//*[@id='__inkstitch_density_plan__']")
if layer is None:
layer = inkex.Group(attrib={
'id': '__inkstitch_density_plan__',
INKSCAPE_LABEL: _('Density Plan'),
INKSCAPE_GROUPMODE: 'layer'
})
svg.append(layer)
else:
# delete old density plan
del layer[:]
# make sure the layer is visible
layer.set('style', 'display:inline')
def create_color_groups(layer):
color_groups = []
colors = [_("Red"), _("Yellow"), _("Green")]
for color in colors:
color_group = inkex.Group(attrib={
'id': '__%s_density_layer__' % color.lower(),
INKSCAPE_LABEL: _('%s density') % color,
})
layer.append(color_group)
color_groups.append(color_group)
return color_groups
def color_block_to_density_markers(svg, groups, stitch_plan, density_options):
num_neighbors = []
for option in density_options:
radius = option['radius'] * PIXELS_PER_MM
num_neighbors.append(get_stitch_density(stitch_plan, radius))
red_group, yellow_group, green_group = groups
for red_neighbors, yellow_neighbors, coord in zip(num_neighbors[0][0], num_neighbors[1][0], num_neighbors[0][1]):
color = "green" # green
group = green_group
if density_options[0]['max_neighbors'] < red_neighbors:
color = "yellow"
group = yellow_group
elif density_options[1]['max_neighbors'] < yellow_neighbors:
color = "red"
group = red_group
density_marker = inkex.Circle(attrib={
'id': svg.get_unique_id("density_marker"),
'style': "fill: %s; stroke: #7e7e7e; stroke-width: 0.02%%;" % color,
'cx': "%s" % coord[0],
'cy': "%s" % coord[1],
'r': str(0.5),
'transform': get_correction_transform(svg)
})
group.append(density_marker)
def get_stitch_density(stitch_plan, radius):
stitches = []
for color_block in stitch_plan:
for stitch in color_block:
stitches.append((stitch.x, stitch.y))
# get density per stitch
tree = KDTree(np.array(stitches))
neighbors = tree.query_ball_tree(tree, radius)
density = [len(i) for i in neighbors], stitches
return density
@cache
def get_correction_transform(svg):
transform = get_viewbox_transform(svg)
# we need to correct for the viewbox
transform = -inkex.transforms.Transform(transform)
return str(transform)

Wyświetl plik

@ -3,14 +3,16 @@
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from inkex import Boolean, Style
from lxml import etree
from inkex import Boolean, Style
from ..stitch_plan import stitch_groups_to_stitch_plan
from ..svg import render_stitch_plan
from ..svg.tags import (INKSCAPE_GROUPMODE, SVG_DEFS_TAG, SVG_GROUP_TAG,
SVG_PATH_TAG)
from ..svg.tags import (INKSCAPE_GROUPMODE, INKSTITCH_ATTRIBS, SVG_DEFS_TAG,
SVG_GROUP_TAG, SVG_PATH_TAG)
from .base import InkstitchExtension
from .stitch_plan_preview_undo import reset_stitch_plan
class StitchPlanPreview(InkstitchExtension):
@ -23,37 +25,37 @@ class StitchPlanPreview(InkstitchExtension):
def effect(self):
# delete old stitch plan
svg = self.document.getroot()
layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']")
if layer is not None:
del layer[:]
reset_stitch_plan(svg)
# create new stitch plan
if not self.get_elements():
return
realistic = False
visual_commands = True
self.metadata = self.get_inkstitch_metadata()
collapse_len = self.metadata['collapse_len_mm']
patches = self.elements_to_stitch_groups(self.elements)
stitch_plan = stitch_groups_to_stitch_plan(patches, collapse_len=collapse_len)
render_stitch_plan(svg, stitch_plan, realistic)
render_stitch_plan(svg, stitch_plan, realistic, visual_commands)
# apply options
layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']")
# update layer visibility 0 = unchanged, 1 = hidden, 2 = lower opacity
groups = self.document.getroot().findall(SVG_GROUP_TAG)
if self.options.layer_visibility == 1:
self.set_invisible_layers_attribute(groups, layer)
self.hide_all_layers()
layer.set('style', None)
layer.style['display'] = "inline"
elif self.options.layer_visibility == 2:
for g in self.document.getroot().findall(SVG_GROUP_TAG):
for g in groups:
style = g.specified_style()
# check groupmode and exclude stitch_plan layer
# exclude objects which are not displayed at all or already have opacity < 0.4
if (g.get(INKSCAPE_GROUPMODE) == "layer" and not g == layer and
float(style.get('opacity', 1)) > 0.4 and not style.get('display', 'inline') == 'none'):
style += Style('opacity:0.4')
g.set("style", style)
g.style['opacity'] = 0.4
# translate stitch plan to the right side of the canvas
if self.options.move_to_side:
@ -65,10 +67,17 @@ class StitchPlanPreview(InkstitchExtension):
if self.options.needle_points:
markers = 'marker-mid:url(#inkstitch-needle-point);marker-start:url(#inkstitch-needle-point);marker-end:url(#inkstitch-needle-point)'
for element in layer.iterdescendants(SVG_PATH_TAG):
style = ';'.join([element.get('style'), markers])
style = element.style + Style(markers)
element.set('style', style)
self.ensure_marker()
def set_invisible_layers_attribute(self, groups, layer):
invisible_layers = []
for g in groups:
if g.get(INKSCAPE_GROUPMODE) == "layer" and 'display' in g.style and g.style['display'] == 'none':
invisible_layers.append(g.get_id())
layer.set(INKSTITCH_ATTRIBS['invisible_layers'], ",".join(invisible_layers))
def ensure_marker(self):
xpath = ".//svg:marker[@id='inkstitch-needle-point']"
point_marker = self.document.getroot().xpath(xpath)

Wyświetl plik

@ -0,0 +1,31 @@
# Authors: see git history
#
# Copyright (c) 2022 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from ..svg.tags import INKSCAPE_GROUPMODE, INKSTITCH_ATTRIBS, SVG_GROUP_TAG
from .base import InkstitchExtension
class StitchPlanPreviewUndo(InkstitchExtension):
def effect(self):
reset_stitch_plan(self.document.getroot())
def reset_stitch_plan(svg):
# delete old stitch plan
layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']")
# get previously invisible layers (they still should be hidden afterwards)
if layer is not None:
invisible_layers = layer.get(INKSTITCH_ATTRIBS['invisible_layers'], '').split(",")
layer.getparent().remove(layer)
# if there are layers with reduced opacity, remove opacity attribute or unhide hidden layers
for g in svg.findall(SVG_GROUP_TAG):
style = g.specified_style()
if (g.get(INKSCAPE_GROUPMODE) == "layer" and float(style.get('opacity', 1)) == 0.4 or style.get('display', 'inline') == 'none'):
if g.get_id() in invisible_layers:
continue
g.style['opacity'] = 1
g.style['display'] = 'inline'

Wyświetl plik

@ -8,10 +8,10 @@ from math import pi
import inkex
from .tags import (INKSCAPE_GROUPMODE, INKSCAPE_LABEL, INKSTITCH_ATTRIBS)
from .units import PIXELS_PER_MM, get_viewbox_transform
from ..i18n import _
from ..utils import Point, cache
from .tags import INKSCAPE_GROUPMODE, INKSCAPE_LABEL, INKSTITCH_ATTRIBS
from .units import PIXELS_PER_MM, get_viewbox_transform
# The stitch vector path looks like this:
# _______

Wyświetl plik

@ -112,6 +112,8 @@ inkstitch_attribs = [
'e_stitch',
'pull_compensation_mm',
'stroke_first',
# stitch_plan
'invisible_layers',
# Legacy
'trim_after',
'stop_after',

Wyświetl plik

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Density Map</name>
<id>org.inkstitch.density_map</id>
<param name="extension" type="string" gui-hidden="true">density_map</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Ink/Stitch" translatable="no">
<submenu name="Visualise and Export" />
</submenu>
</effects-menu>
</effect>
<label appearance="header">Red markers</label>
<param name="num-neighbors-red" gui-text="Number of stitches" gui-description="0 = no density info" type="int" min="0" max="99" indents="1">6</param>
<param name="density-radius-red" gui-text="within a radius (mm) of" type="float" min="0" max="50" indents="1">0.5</param>
<spacer />
<label appearance="header">Yellow markers</label>
<param name="num-neighbors-yellow" gui-text="Number of stitches" gui-description="0 = no density info" type="int" min="0" max="99" indents="1">3</param>
<param name="density-radius-yellow" gui-text="within a radius (mm) of" type="float" min="0" max="50">0.5</param>
<spacer />
<param name="layer-visibility" type="optiongroup" appearance="combo" gui-text="Design layer visibility" indents="1">
<option value="0">Unchanged</option>
<option value="1">Hidden</option>
<option value="2">Lower opacity</option>
</param>
<script>
{{ command_tag | safe }}
</script>
</inkscape-extension>

Wyświetl plik

@ -18,8 +18,7 @@
<option value="2">Lower opacity</option>
</param>
<param name="needle-points" type="boolean" gui-text="Needle points">false</param>
<separator />
<label>Hit Ctrl+Z to undo this action after inspection.</label>
<spacer />
<script>
{{ command_tag | safe }}
</script>

Wyświetl plik

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Undo Stitch Plan Preview</name>
<id>org.inkstitch.stitch_plan_preview_undo</id>
<param name="extension" type="string" gui-hidden="true">stitch_plan_preview_undo</param>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu name="Ink/Stitch" translatable="no">
<submenu name="Visualise and Export" />
</submenu>
</effects-menu>
</effect>
<script>
{{ command_tag | safe }}
</script>
</inkscape-extension>