diff --git a/extensions/fablabchemnitz/boundingbox.py b/extensions/fablabchemnitz/boundingbox.py index 342b4df9..b01ed812 100644 --- a/extensions/fablabchemnitz/boundingbox.py +++ b/extensions/fablabchemnitz/boundingbox.py @@ -36,8 +36,8 @@ class DrawBBoxes(inkex.EffectExtension): def effect(self): if len(self.svg.selected) > 0: if self.options.split is False: - for id, item in self.svg.selected.items(): - self.drawBBox(item.bounding_box()) + for element in self.svg.selected.values(): + self.drawBBox(element.bounding_box()) else: #self.drawBBox(self.svg.get_selected_bbox()) #works for InkScape (1:1.0+devel+202008292235+eff2292935) @ Linux and for Windows (but with deprecation) self.drawBBox(self.svg.selection.bounding_box()) #works for InkScape 1.1dev (9b1fc87, 2020-08-27)) @ Windows diff --git a/extensions/fablabchemnitz/create_links.py b/extensions/fablabchemnitz/create_links.py index 65768841..edd29aa0 100644 --- a/extensions/fablabchemnitz/create_links.py +++ b/extensions/fablabchemnitz/create_links.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # coding=utf-8 # # Copyright (C) 2005,2007 Aaron Spike, aaron@ekips.org @@ -76,7 +76,7 @@ class LinksCreator(inkex.EffectExtension): if raw[i][0] == 'M' and i != 0: subPaths.append(raw[prev:i]) prev = i - subPaths.append(raw[prev:]) + subPaths.append(raw[prev:]) for subpath in subPaths: replacedNode = copy.copy(node) oldId = replacedNode.get('id') @@ -139,7 +139,7 @@ class LinksCreator(inkex.EffectExtension): if self.options.switch_pattern is True: dashes = dashes[::-1] #reverse the array - #validate dashes. May not be negative. Otherwise Inkscape will freeze forever. Reason: rendering issue + #validate dashes. May not be negative (dash or gap cannot be longer than the path itself). Otherwise Inkscape will freeze forever. Reason: rendering issue if any(dash <= 0.0 for dash in dashes) == True: if self.options.show_info is True: self.msg("node " + node.get('id') + ": Error! Dash array may not contain negative numbers: " + ' '.join(format(dash, "1.3f") for dash in dashes) + ". Path skipped. Maybe it's too short. Adjust your link count, multiplicator and length accordingly, or set to unit '%'") return False if self.options.skip_errors is True else exit(1) @@ -267,11 +267,10 @@ class LinksCreator(inkex.EffectExtension): dash = dash - length length = bezier.cspseglength(new[-1][-1], sub[i]) while dash < length: - new[-1][-1], nxt, sub[i] = \ - bezier.cspbezsplitatlength(new[-1][-1], sub[i], dash/length) - if idash % 2: # create a gap + new[-1][-1], nxt, sub[i] = bezier.cspbezsplitatlength(new[-1][-1], sub[i], dash/length) + if idash % 2: # create a gap new.append([nxt[:]]) - else: # splice the curve + else: # splice the curve new[-1].append(nxt[:]) length = length - dash idash = (idash + 1) % len(dashes) @@ -283,22 +282,44 @@ class LinksCreator(inkex.EffectExtension): i += 1 style.pop('stroke-dasharray') node.pop('sodipodi:type') + csp = CubicSuperPath(new) node.path = CubicSuperPath(new) node.style = style # break apart the combined path to have multiple elements if self.options.breakapart is True: - breakOutputNodes = self.breakContours(node) + breakOutputNodes = None + breakOutputNodes = self.breakContours(node, breakOutputNodes) breakApartGroup = nodeParent.add(inkex.Group()) for breakOutputNode in breakOutputNodes: breakApartGroup.append(breakOutputNode) #self.msg(replacedNode.get('id')) #self.svg.selection.set(replacedNode.get('id')) #update selection to split paths segments (does not work, so commented out) - + + #cleanup useless points + p = breakOutputNode.path + commandsCoords = p.to_arrays() + # "m 45.250809,91.692739" - this path contains onyl one command - a single point + if len(commandsCoords) == 1: + breakOutputNode.delete() + # "m 45.250809,91.692739 z" - this path contains two commands, but only one coordinate. + # It's a single point, the path is closed by a Z command + elif len(commandsCoords) == 2 and commandsCoords[0][1] == commandsCoords[1][1]: + breakOutputNode.delete() + # "m 45.250809,91.692739 l 45.250809,91.692739" - this path contains two commands, + # but the first and second coordinate are the same. It will render als point + elif len(commandsCoords) == 2 and commandsCoords[-1][0] == 'Z': + breakOutputNode.delete() + # "m 45.250809,91.692739 l 45.250809,91.692739 z" - this path contains three commands, + # but the first and second coordinate are the same. It will render als point, the path is closed by a Z command + elif len(commandsCoords) == 3 and commandsCoords[0][1] == commandsCoords[1][1] and commandsCoords[2][1] == 'Z': + breakOutputNode.delete() + if len(self.svg.selected) > 0: for node in self.svg.selection.values(): #at first we need to break down combined nodes to single path, otherwise dasharray cannot properly be applied - breakInputNodes = self.breakContours(node) + breakInputNodes = None + breakInputNodes = self.breakContours(node, breakInputNodes) for breakInputNode in breakInputNodes: createLinks(breakInputNode) else: diff --git a/extensions/fablabchemnitz/purge_pointy_paths.inx b/extensions/fablabchemnitz/purge_pointy_paths.inx new file mode 100644 index 00000000..66f529eb --- /dev/null +++ b/extensions/fablabchemnitz/purge_pointy_paths.inx @@ -0,0 +1,16 @@ + + + Purge Pointy Paths + fablabchemnitz.de.purge_pointy_paths + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/purge_pointy_paths.py b/extensions/fablabchemnitz/purge_pointy_paths.py new file mode 100644 index 00000000..050368ae --- /dev/null +++ b/extensions/fablabchemnitz/purge_pointy_paths.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +""" +This filter deletes paths which render as point only + +More usesless and/or redundant filters for removing duplicate nodes and segments are provided by the following extension: +- https://stadtfabrikanten.org/display/IFM/Purge+Duplicate+Path+Segments +- https://stadtfabrikanten.org/display/IFM/Purge+Duplicate+Path+Nodes + +Extension for InkScape 1.X +Author: Mario Voigt / FabLab Chemnitz +Mail: mario.voigt@stadtfabrikanten.org +Date: 21.04.2021 +Last patch: 21.04.2021 +License: GNU GPL v3 +""" + +import inkex +from lxml import etree + +class PurgeInvalidPaths(inkex.EffectExtension): + + def effect(self): + if len(self.svg.selected) > 0: + for element in self.svg.selected.values(): + if isinstance(element, inkex.PathElement): + p = element.path + commandsCoords = p.to_arrays() + # "m 45.250809,91.692739" - this path contains onyl one command - a single point + if len(commandsCoords) == 1: + element.delete() + # "m 45.250809,91.692739 z" - this path contains two commands, but only one coordinate. + # It's a single point, the path is closed by a Z command + elif len(commandsCoords) == 2 and commandsCoords[0][1] == commandsCoords[1][1]: + element.delete() + # "m 45.250809,91.692739 l 45.250809,91.692739" - this path contains two commands, + # but the first and second coordinate are the same. It will render als point + elif len(commandsCoords) == 2 and commandsCoords[-1][0] == 'Z': + element.delete() + # "m 45.250809,91.692739 l 45.250809,91.692739 z" - this path contains three commands, + # but the first and second coordinate are the same. It will render als point, the path is closed by a Z command + elif len(commandsCoords) == 3 and commandsCoords[0][1] == commandsCoords[1][1] and commandsCoords[2][1] == 'Z': + element.delete() + else: + inkex.errormsg('Please select some objects first.') + return + +if __name__ == '__main__': + PurgeInvalidPaths().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/remove_redundant.py b/extensions/fablabchemnitz/remove_redundant.py index 48b2456a..8b578b16 100644 --- a/extensions/fablabchemnitz/remove_redundant.py +++ b/extensions/fablabchemnitz/remove_redundant.py @@ -59,9 +59,9 @@ class RemoveRedundant(inkex.EffectExtension): seenSegments = set() coordsCache = FixedRadiusSearch() - for id, node in self.svg.selected.items(): - if node.tag == inkex.addNS('path','svg'): - d = node.get('d') + for element in self.svg.selected.values(): + if element.tag == inkex.addNS('path','svg'): + d = element.get('d') path = paths.CubicSuperPath(d).to_path().to_arrays() newPath = [] start = prev = None @@ -117,7 +117,7 @@ class RemoveRedundant(inkex.EffectExtension): newPath.append([command, coords]) while len(newPath) and newPath[-1][0] == 'M': newPath = newPath[:-1] - node.set('d',str(paths.Path(newPath))) + element.set('d',str(paths.Path(newPath))) if __name__ == '__main__': RemoveRedundant().run() \ No newline at end of file