diff options
| author | Kaalleen <36401965+kaalleen@users.noreply.github.com> | 2025-01-05 12:46:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-05 12:46:06 +0100 |
| commit | be66297da6aec234ef807b20609943f3c3252c2f (patch) | |
| tree | 9f49c4e1bc104afe4bdf45eb5977fe43eecc81de | |
| parent | 23c2bf446aac5a2ac95e25719510252f6172f415 (diff) | |
Redwork: add combine option (#3407)
* add keep originals option
| -rw-r--r-- | lib/extensions/redwork.py | 95 | ||||
| -rw-r--r-- | lib/lettering/font.py | 2 | ||||
| -rw-r--r-- | templates/redwork.xml | 9 |
3 files changed, 67 insertions, 39 deletions
diff --git a/lib/extensions/redwork.py b/lib/extensions/redwork.py index 9ad2aca5..9ec5cfc2 100644 --- a/lib/extensions/redwork.py +++ b/lib/extensions/redwork.py @@ -4,7 +4,8 @@ # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. import networkx as nx -from inkex import Group, Path, PathElement, errormsg +from inkex import Boolean, Group, Path, PathElement, errormsg +from inkex.paths.lines import Line from shapely import length, unary_union from shapely.geometry import LineString, MultiLineString, Point from shapely.ops import linemerge, nearest_points, substring @@ -24,10 +25,12 @@ class Redwork(InkstitchExtension): InkstitchExtension.__init__(self, *args, **kwargs) self.arg_parser.add_argument("--notebook") + self.arg_parser.add_argument("-c", "--combine", dest="combine", type=Boolean, default=False) self.arg_parser.add_argument("-m", "--merge_distance", dest="merge_distance", type=float, default=0.5) self.arg_parser.add_argument("-p", "--minimum_path_length", dest="minimum_path_length", type=float, default=0.5) self.arg_parser.add_argument("-s", "--redwork_running_stitch_length_mm", dest="redwork_running_stitch_length_mm", type=float, default=2.5) self.arg_parser.add_argument("-b", "--redwork_bean_stitch_repeats", dest="redwork_bean_stitch_repeats", type=str, default='0') + self.arg_parser.add_argument("-k", "--keep_originals", dest="keep_originals", type=Boolean, default=False) self.elements = None self.graph = None @@ -57,9 +60,15 @@ class Redwork(InkstitchExtension): multi_line_string = self._ensure_starting_point(multi_line_string, starting_point) self._build_graph(multi_line_string) + redwork_group = self._create_redwork_group() self._generate_strongly_connected_components() self._generate_eulerian_circuits() - self._eulerian_circuits_to_elements(elements) + self._eulerian_circuits_to_elements(redwork_group, elements) + + # remove input elements + if not self.options.keep_originals: + for element in elements: + element.node.getparent().remove(element.node) def _ensure_starting_point(self, multi_line_string, starting_point): # returns a MultiLineString whose first LineString starts close to starting_point @@ -92,55 +101,69 @@ class Redwork(InkstitchExtension): # return the first occurence directly return command.target_point - def _eulerian_circuits_to_elements(self, elements): - node = elements[0].node - index = node.getparent().index(node) - style = node.style - transform = get_correction_transform(node) - nb_circuits = len(self.eulerian_circuit) + def _create_redwork_group(self): + node = self.svg.selection.rendering_order()[-1] + parent = node.getparent() + index = parent.index(node) + 1 # create redwork group redwork_group = Group() redwork_group.label = _("Redwork Group") - node.getparent().insert(index, redwork_group) + parent.insert(index, redwork_group) + return redwork_group + + def _eulerian_circuits_to_elements(self, redwork_group, elements): + combine_all = self.options.combine and self.options.redwork_bean_stitch_repeats == '0' + node = elements[0].node + style = node.style + transform = get_correction_transform(self.svg.selection.rendering_order()[0]) # insert lines grouped by underpath and top layer visited_lines = [] i = 1 for circuit in self.eulerian_circuit: + previous_element_type = False connected_group = Group() connected_group.label = _("Connected Group") + if len(self.eulerian_circuit) > 1: + redwork_group.insert(i, connected_group) + group = connected_group + else: + group = redwork_group + path = '' for edge in circuit: linestring = self.graph.get_edge_data(edge[0], edge[1], edge[2])['path'] + if length(linestring) < self.minimum_path_length: + continue - if length(linestring) > self.minimum_path_length: - current_line = linestring - if current_line in visited_lines: - path_id = self.svg.get_unique_id('redwork_') - label = _("Redwork") + f' {i}' - redwork = True - - else: - path_id = self.svg.get_unique_id('underpath_') - label = _("Redwork Underpath") + f' {i}' - visited_lines.append(current_line.reverse()) - redwork = False - - path = str(Path(list(current_line.coords))) - if nb_circuits > 1: - redwork_group.insert(i, connected_group) - self._insert_element(path, connected_group, style, transform, label, path_id, redwork) - else: - self._insert_element(path, redwork_group, style, transform, label, path_id, redwork) - - i += 1 - - # remove input elements - for element in elements: - element.node.getparent().remove(element.node) - - def _insert_element(self, path, group, style, transform, label, path_id, redwork=True): + if linestring in visited_lines: + redwork = True + else: + redwork = False + visited_lines.append(linestring.reverse()) + + current_path = Path(list(linestring.coords)) + if not self.options.combine or (not combine_all and previous_element_type != redwork): + if path: + self._insert_element(i, path, group, style, transform, previous_element_type) + i += 1 + path = str(current_path) + else: + if path: + current_path[0] = Line(current_path[0].x, current_path[0].y) + path += str(current_path) + previous_element_type = redwork + if path: + self._insert_element(i, path, group, style, transform, redwork) + + def _insert_element(self, index, path, group, style, transform, redwork=True): + if redwork: + path_id = self.svg.get_unique_id('redwork_') + label = _("Redwork") + f' {index}' + else: + path_id = self.svg.get_unique_id('underpath_') + label = _("Redwork Underpath") + f' {index}' element = PathElement( id=path_id, diff --git a/lib/lettering/font.py b/lib/lettering/font.py index cc99202b..6127a84c 100644 --- a/lib/lettering/font.py +++ b/lib/lettering/font.py @@ -577,7 +577,7 @@ class Font(object): group.append(color_group) - def _get_color_sorted_elements(self, group, transform_key): + def _get_color_sorted_elements(self, group, transform_key): # noqa: 901 elements_by_color = defaultdict(list) last_parent = None diff --git a/templates/redwork.xml b/templates/redwork.xml index 789bbd1f..4f71209c 100644 --- a/templates/redwork.xml +++ b/templates/redwork.xml @@ -15,10 +15,15 @@ <param name="redwork_running_stitch_length_mm" type="float" precision="2" min="0" max="500" gui-text="Redwork stitch length (mm)" gui-description="set redwork stitch length">2.5</param> - <param name="redwork_bean_stitch_repeats" type="string" precision="0" min="0" max="500" + <param name="redwork_bean_stitch_repeats" type="string" gui-text="Redwork bean stitch number of repeats" gui-description="Redwork bean stitch number of repeats">0</param> - + <spacer /> + <separator /> + <spacer /> + <param name="combine" type="boolean" gui-text="Combine elements" + gui-description="Combine consecutive elements of same type">false</param> + <param name="keep_originals" type="boolean" gui-text="Keep original paths">false</param> </page> <page name="info" gui-text="Help"> <label>Redwork embroidery is a stroke art embroidery which passes every line exactly twice.</label> |
