Added several fixes for create_links extension

This commit is contained in:
Mario Voigt 2021-04-13 14:44:28 +02:00
parent 48c9a9630e
commit 18dc01e884
2 changed files with 178 additions and 142 deletions

View File

@ -4,6 +4,11 @@
<id>fablabchemnitz.de.create_links</id> <id>fablabchemnitz.de.create_links</id>
<param name="main_tabs" type="notebook"> <param name="main_tabs" type="notebook">
<page name="settings" gui-text="Settings"> <page name="settings" gui-text="Settings">
<param name="path_types" type="optiongroup" appearance="combo" gui-text="Apply for">
<option value="open_paths">open paths</option>
<option value="closed_paths">closed paths</option>
<option value="both">both</option>
</param>
<param name="unit" type="optiongroup" appearance="combo" gui-text="Units"> <param name="unit" type="optiongroup" appearance="combo" gui-text="Units">
<option value="mm">mm</option> <option value="mm">mm</option>
<option value="cm">cm</option> <option value="cm">cm</option>
@ -14,15 +19,15 @@
<option value="percent">%</option> <option value="percent">%</option>
</param> </param>
<param name="link_count" type="int" min="1" max="9999" gui-text="Link count">1</param> <param name="link_count" type="int" min="1" max="9999" gui-text="Link count">1</param>
<param name="link_multiplicator (experimental)" type="int" min="0" max="9999" gui-text="Link multiplicator" gui-description="If se, we create a set of multiple gaps of same size next to the main gap">0</param>
<param name="length_link" type="float" min="0.000" max="9999.000" precision="3" gui-text="Link length (the length of the gap)">1.000</param> <param name="length_link" type="float" min="0.000" max="9999.000" precision="3" gui-text="Link length (the length of the gap)">1.000</param>
<param name="link_offset" type="float" min="-9999.000.000" max="9999.000" precision="3" gui-text="Link offset (+/-)">0.000</param> <param name="link_multiplicator" type="int" min="0" max="9999" gui-text="Link multiplicator (experimental)" gui-description="If set, we create a set of multiple gaps of same size next to the main gap">0</param>
<param name="link_offset" type="float" min="-9999.000.000" max="9999.000" precision="3" gui-text="Link offset (+/-) (experimental)" gui-description="Does not properly work the intended way if link count is more than 1.">0.000</param>
<param name="length_filter" type="bool" gui-text="Enable path length filtering">false</param> <param name="length_filter" type="bool" gui-text="Enable path length filtering">false</param>
<param name="length_filter_value" type="float" min="0.000" max="9999.000" precision="3" gui-text="Paths with length more than">0.000</param> <param name="length_filter_value" type="float" min="0.000" max="9999.000" precision="3" gui-text="Paths with length more than">0.000</param>
<param name="custom_dasharray" type="bool" gui-text="Enable custom dash pattern">false</param> <param name="custom_dasharray" type="bool" gui-text="Enable custom dash pattern">false</param>
<param name="custom_dasharray_value" type="string" gui-text="Dash pattern" gui-description="A list of separated lengths that specify the lengths of alternating dashes and gaps. Input only accepts numbers. It ignores percentages or other characters.">10 5</param> <param name="custom_dasharray_value" type="string" gui-text="Dash pattern" gui-description="A list of separated lengths that specify the lengths of alternating dashes and gaps. Input only accepts numbers. It ignores percentages or other characters.">10 5</param>
<param name="keep_selected" type="bool" gui-text="Keep selected elements">false</param> <param name="keep_selected" type="bool" gui-text="Keep selected elements">false</param>
<param name="breakapart" type="bool" gui-text="Break apart" gui-description="Performs CTRL + SHIFT + K to break a combined path into it's parts">false</param> <param name="breakapart" type="bool" gui-text="Break apart output paths" gui-description="Performs CTRL + SHIFT + K to break the new output path into it's parts">false</param>
<param name="show_info" type="bool" gui-text="Print some length and pattern information" gui-description="Warning: might freeze InkScape forever if you have a lot of nodes because we create too much print output. Use for debugging only!">false</param> <param name="show_info" type="bool" gui-text="Print some length and pattern information" gui-description="Warning: might freeze InkScape forever if you have a lot of nodes because we create too much print output. Use for debugging only!">false</param>
</page> </page>
<page name="about" gui-text="About"> <page name="about" gui-text="About">

View File

@ -24,6 +24,10 @@ It is a modification of the file addnodes.py
It is a modification of the file convert2dash.py It is a modification of the file convert2dash.py
Extension to convert paths into dash-array line Extension to convert paths into dash-array line
ToDo:
- better handling of dasharray patterns (fix experimental stuff with multiplicator)
- dash offset does not behave the exspected way
- break apart before calculating
""" """
import copy import copy
@ -38,22 +42,23 @@ class LinksCreator(inkex.EffectExtension):
def __init__(self): def __init__(self):
super(LinksCreator, self).__init__() super(LinksCreator, self).__init__()
self.arg_parser.add_argument("--main_tabs") self.arg_parser.add_argument("--main_tabs")
self.arg_parser.add_argument("--path_types", default="closed_paths", help="Apply for closed paths, open paths or both")
self.arg_parser.add_argument("--unit", default="mm", help="Units") self.arg_parser.add_argument("--unit", default="mm", help="Units")
self.arg_parser.add_argument("--link_count", type=int, default=1, help="Link count") self.arg_parser.add_argument("--link_count", type=int, default=1, help="Link count")
self.arg_parser.add_argument("--link_multiplicator", type=int, default=1, help="If se, we create a set of multiple gaps of same size next to the main gap")
self.arg_parser.add_argument("--length_link", type=float, default=1.000, help="Link length") self.arg_parser.add_argument("--length_link", type=float, default=1.000, help="Link length")
self.arg_parser.add_argument("--link_offset", type=float, default=0.000, help="Link offset (+/-)") self.arg_parser.add_argument("--link_multiplicator", type=int, default=1, help="If set, we create a set of multiple gaps of same size next to the main gap")
self.arg_parser.add_argument("--link_offset", type=float, default=0.000, help="Link offset (+/-). Does not properly work the intended way if link count is more than 1.")
self.arg_parser.add_argument("--length_filter", type=inkex.Boolean, default=False, help="Enable path length filtering") self.arg_parser.add_argument("--length_filter", type=inkex.Boolean, default=False, help="Enable path length filtering")
self.arg_parser.add_argument("--length_filter_value", type=float, default=0.000, help="Paths with length more than") self.arg_parser.add_argument("--length_filter_value", type=float, default=0.000, help="Paths with length more than")
self.arg_parser.add_argument("--custom_dasharray", type=inkex.Boolean, default=False, help="Enable custom dash pattern") self.arg_parser.add_argument("--custom_dasharray", type=inkex.Boolean, default=False, help="Enable custom dash pattern")
self.arg_parser.add_argument("--custom_dasharray_value", default="", help="A list of separated lengths that specify the lengths of alternating dashes and gaps. Input only accepts numbers. It ignores percentages or other characters.") self.arg_parser.add_argument("--custom_dasharray_value", default="", help="A list of separated lengths that specify the lengths of alternating dashes and gaps. Input only accepts numbers. It ignores percentages or other characters.")
self.arg_parser.add_argument("--keep_selected", type=inkex.Boolean, default=False, help="Keep selected elements") self.arg_parser.add_argument("--keep_selected", type=inkex.Boolean, default=False, help="Keep selected elements")
self.arg_parser.add_argument("--breakapart", type=inkex.Boolean, default=False, help="Performs CTRL + SHIFT + K to break a combined path into it's parts") self.arg_parser.add_argument("--breakapart", type=inkex.Boolean, default=False, help="Performs CTRL + SHIFT + K to break the new output path into it's parts")
self.arg_parser.add_argument("--show_info", type=inkex.Boolean, default=False, help="Print some length and pattern information") self.arg_parser.add_argument("--show_info", type=inkex.Boolean, default=False, help="Print some length and pattern information")
replacedNodes = [] def breakContours(self, node, breakNodes = None): #this does the same as "CTRL + SHIFT + K"
if breakNodes == None:
def breakContours(self, node): #this does the same as "CTRL + SHIFT + K" breakNodes = []
parent = node.getparent() parent = node.getparent()
idx = parent.index(node) idx = parent.index(node)
idSuffix = 0 idSuffix = 0
@ -67,19 +72,29 @@ class LinksCreator(inkex.EffectExtension):
for subpath in subPaths: for subpath in subPaths:
replacedNode = copy.copy(node) replacedNode = copy.copy(node)
oldId = replacedNode.get('id') oldId = replacedNode.get('id')
replacedNode.set('d', CubicSuperPath(subpath)) replacedNode.set('d', CubicSuperPath(subpath))
replacedNode.set('id', oldId + str(idSuffix).zfill(5)) replacedNode.set('id', oldId + str(idSuffix).zfill(5))
parent.insert(idx, replacedNode) parent.insert(idx, replacedNode)
idSuffix += 1 idSuffix += 1
self.replacedNodes.append(replacedNode) breakNodes.append(replacedNode)
parent.remove(node) parent.remove(node)
for child in node: return breakNodes
self.breakContours(child)
def effect(self): def effect(self):
if len(self.svg.selected) > 0: def createLinks(node):
for node in self.svg.selection.filter(PathElement).values(): nodeParent = node.getparent()
pathIsClosed = False
path = node.path.to_superpath()
if path[-1][0] == 'Z' or path[0] == path[-1]: #if first is last point the path is also closed. The "Z" command is not required
pathIsClosed = True
if self.options.path_types == 'open_paths' and pathIsClosed is True:
return #skip this loop iteration
elif self.options.path_types == 'closed_paths' and pathIsClosed is False:
return #skip this loop iteration
elif self.options.path_types == 'both':
pass
if self.options.keep_selected is True: if self.options.keep_selected is True:
parent = node.getparent() parent = node.getparent()
@ -91,12 +106,16 @@ class LinksCreator(inkex.EffectExtension):
csp = node.path.transform(node.composed_transform()).to_superpath() csp = node.path.transform(node.composed_transform()).to_superpath()
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
if self.options.unit == "percent":
length_link = (self.options.length_link / 100.0) * stotal
else:
length_link = self.svg.unittouu(str(self.options.length_link) + self.options.unit) length_link = self.svg.unittouu(str(self.options.length_link) + self.options.unit)
if self.options.length_filter is True: if self.options.length_filter is True:
if stotal < self.options.length_filter_value: if stotal < self.options.length_filter_value:
if self.options.show_info is True:
inkex.utils.debug("node " + node.get('id') + " is shorter than minimum allowed length of {:1.3f}. Path length is {:1.3f}".format(self.options.length_filter_value, stotal)) inkex.utils.debug("node " + node.get('id') + " is shorter than minimum allowed length of {:1.3f}. Path length is {:1.3f}".format(self.options.length_filter_value, stotal))
break return #skip this loop iteration
''' '''
<dasharray> <dasharray>
@ -137,11 +156,15 @@ class LinksCreator(inkex.EffectExtension):
if self.options.show_info is True: if self.options.show_info is True:
inkex.utils.debug("node " + node.get('id')) inkex.utils.debug("node " + node.get('id'))
inkex.utils.debug("total path length = {:1.3f} {}".format(self.svg.uutounit(stotal, self.options.unit), self.options.unit)) #show length, converted in selected unit if self.options.unit == "percent":
inkex.utils.debug("total path length = {:1.3f} {}".format(stotal, self.svg.unit)) #show length, converted in selected unit
else:
inkex.utils.debug("total path length = {:1.3f} {} ({:1.3f} {})".format(self.svg.uutounit(stotal, self.options.unit), self.options.unit, stotal, self.svg.unit)) #show length, converted in selected unit
inkex.utils.debug("total gaps = {}".format(self.options.link_count)) inkex.utils.debug("total gaps = {}".format(self.options.link_count))
inkex.utils.debug("(calculated) dash/gap pattern: {} ({})".format(stroke_dasharray, self.options.unit)) inkex.utils.debug("(calculated) gap length: {:1.3f} {}".format(length_link, self.options.unit))
inkex.utils.debug("(calculated) dash/gap pattern: {} ({})".format(stroke_dasharray, self.svg.unit))
inkex.utils.debug("(calculated) dash offset: {:1.3f} {}".format(self.svg.uutounit(stroke_dashoffset, self.options.unit), self.options.unit)) inkex.utils.debug("(calculated) dash offset: {:1.3f} {}".format(self.svg.uutounit(stroke_dashoffset, self.options.unit), self.options.unit))
inkex.utils.debug("----------------------------------------------------------------") inkex.utils.debug("--------------------------------------------------------------------------------------------------")
# check if the node has a style attribute. If not we create a blank one with a black stroke and without fill # check if the node has a style attribute. If not we create a blank one with a black stroke and without fill
style = None style = None
@ -205,17 +228,25 @@ class LinksCreator(inkex.EffectExtension):
else: else:
new[-1].append(sub[i]) new[-1].append(sub[i])
i += 1 i += 1
#style.pop('stroke-dasharray') style.pop('stroke-dasharray')
node.pop('sodipodi:type') node.pop('sodipodi:type')
node.path = CubicSuperPath(new) node.path = CubicSuperPath(new)
node.style = style node.style = style
if self.options.breakapart is True: if self.options.breakapart is True:
self.breakContours(node) breakOutputNodes = self.breakContours(node)
#update selection to split paths segments (does not work, so commented out) breakApartGroup = nodeParent.add(inkex.Group())
#for replacedNode in self.replacedNodes: for breakOutputNode in breakOutputNodes:
# inkex.utils.debug(replacedNode.get('id')) breakApartGroup.append(breakOutputNode)
# self.svg.selection.set(replacedNode.get('id')) #inkex.utils.debug(replacedNode.get('id'))
#self.svg.selection.set(replacedNode.get('id')) #update selection to split paths segments (does not work, so commented out)
if len(self.svg.selected) > 0:
for node in self.svg.selection.filter(PathElement).values():
#at first we need to break down combined nodes to single path, otherwise dasharray cannot properly be applied
breakInputNodes = self.breakContours(node)
for breakInputNode in breakInputNodes:
createLinks(breakInputNode)
else: else:
inkex.errormsg('Please select some objects first.') inkex.errormsg('Please select some objects first.')